mirror of
https://github.com/trezor/trezor-wallet
synced 2025-01-21 05:21:08 +00:00
add copy log to clipboard button
This commit is contained in:
parent
fd2582dc51
commit
0add59669b
@ -1,6 +1,7 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
import * as LOG from 'actions/constants/log';
|
import * as LOG from 'actions/constants/log';
|
||||||
|
import copy from 'copy-to-clipboard';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Action, ThunkAction, GetState, Dispatch,
|
Action, ThunkAction, GetState, Dispatch,
|
||||||
@ -11,6 +12,8 @@ export type LogAction = {
|
|||||||
type: typeof LOG.OPEN,
|
type: typeof LOG.OPEN,
|
||||||
} | {
|
} | {
|
||||||
type: typeof LOG.CLOSE,
|
type: typeof LOG.CLOSE,
|
||||||
|
} | {
|
||||||
|
type: typeof LOG.COPY_SUCCESS,
|
||||||
} | {
|
} | {
|
||||||
type: typeof LOG.ADD,
|
type: typeof LOG.ADD,
|
||||||
payload: LogEntry
|
payload: LogEntry
|
||||||
@ -38,3 +41,17 @@ export const add = (type: string, message: any): Action => ({
|
|||||||
message,
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -4,3 +4,4 @@
|
|||||||
export const OPEN: 'log__open' = 'log__open';
|
export const OPEN: 'log__open' = 'log__open';
|
||||||
export const CLOSE: 'log__close' = 'log__close';
|
export const CLOSE: 'log__close' = 'log__close';
|
||||||
export const ADD: 'log__add' = 'log__add';
|
export const ADD: 'log__add' = 'log__add';
|
||||||
|
export const COPY_SUCCESS: 'log__copy_success' = 'log__copy_success';
|
@ -5,6 +5,8 @@ import { bindActionCreators } from 'redux';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import { H2 } from 'components/Heading';
|
import { H2 } from 'components/Heading';
|
||||||
|
import Button from 'components/Button';
|
||||||
|
import Tooltip from 'components/Tooltip';
|
||||||
import ReactJson from 'react-json-view';
|
import ReactJson from 'react-json-view';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import P from 'components/Paragraph';
|
import P from 'components/Paragraph';
|
||||||
@ -18,7 +20,8 @@ import l10nMessages from './index.messages';
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
log: $ElementType<State, 'log'>,
|
log: $ElementType<State, 'log'>,
|
||||||
toggle: typeof LogActions.toggle
|
toggle: typeof LogActions.toggle,
|
||||||
|
copyToClipboard: typeof LogActions.copyToClipboard
|
||||||
}
|
}
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
@ -60,8 +63,22 @@ const LogWrapper = styled.div`
|
|||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const CopyWrapper = styled.div`
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ButtonCopy = styled(Button)`
|
||||||
|
margin-top: 10px;
|
||||||
|
max-width: 200px;
|
||||||
|
`;
|
||||||
|
|
||||||
const Log = (props: Props): ?React$Element<string> => {
|
const Log = (props: Props): ?React$Element<string> => {
|
||||||
if (!props.log.opened) return null;
|
if (!props.log.opened) return null;
|
||||||
|
|
||||||
|
const copyBtn = (
|
||||||
|
<ButtonCopy onClick={() => props.copyToClipboard()}>
|
||||||
|
<FormattedMessage {...l10nMessages.TR_COPY_TO_CLIPBOARD} />
|
||||||
|
</ButtonCopy>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Click onClick={props.toggle}>
|
<Click onClick={props.toggle}>
|
||||||
@ -76,6 +93,20 @@ const Log = (props: Props): ?React$Element<string> => {
|
|||||||
<LogWrapper>
|
<LogWrapper>
|
||||||
<ReactJson src={props.log.entries} />
|
<ReactJson src={props.log.entries} />
|
||||||
</LogWrapper>
|
</LogWrapper>
|
||||||
|
{props.log.copied ? (
|
||||||
|
<Tooltip
|
||||||
|
defaultVisible
|
||||||
|
maxWidth={285}
|
||||||
|
placement="top"
|
||||||
|
content={<FormattedMessage {...l10nMessages.TR_COPIED} />}
|
||||||
|
>
|
||||||
|
|
||||||
|
{copyBtn}
|
||||||
|
</Tooltip>
|
||||||
|
) : (
|
||||||
|
<CopyWrapper>{copyBtn}</CopyWrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -86,5 +117,6 @@ export default connect(
|
|||||||
}),
|
}),
|
||||||
(dispatch: Dispatch) => ({
|
(dispatch: Dispatch) => ({
|
||||||
toggle: bindActionCreators(LogActions.toggle, dispatch),
|
toggle: bindActionCreators(LogActions.toggle, dispatch),
|
||||||
|
copyToClipboard: bindActionCreators(LogActions.copyToClipboard, dispatch),
|
||||||
}),
|
}),
|
||||||
)(Log);
|
)(Log);
|
@ -12,6 +12,14 @@ const definedMessages: Messages = defineMessages({
|
|||||||
defaultMessage: 'Log',
|
defaultMessage: 'Log',
|
||||||
description: 'application event and error',
|
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;
|
export default definedMessages;
|
@ -34,12 +34,14 @@ const Tooltip = ({
|
|||||||
readMoreLink,
|
readMoreLink,
|
||||||
children,
|
children,
|
||||||
enterDelayMs,
|
enterDelayMs,
|
||||||
|
defaultVisible = false,
|
||||||
}) => (
|
}) => (
|
||||||
<Wrapper className={className}>
|
<Wrapper className={className}>
|
||||||
<RcTooltip
|
<RcTooltip
|
||||||
arrowContent={<div className="rc-tooltip-arrow-inner" />}
|
arrowContent={<div className="rc-tooltip-arrow-inner" />}
|
||||||
placement={placement}
|
placement={placement}
|
||||||
mouseEnterDelay={enterDelayMs || 0}
|
mouseEnterDelay={enterDelayMs || 0}
|
||||||
|
defaultVisible={defaultVisible}
|
||||||
overlay={() => (
|
overlay={() => (
|
||||||
<ContentWrapper>
|
<ContentWrapper>
|
||||||
<Content maxWidth={maxWidth}>{content}</Content>
|
<Content maxWidth={maxWidth}>{content}</Content>
|
||||||
@ -71,6 +73,7 @@ Tooltip.propTypes = {
|
|||||||
]),
|
]),
|
||||||
readMoreLink: PropTypes.string,
|
readMoreLink: PropTypes.string,
|
||||||
enterDelayMs: PropTypes.number,
|
enterDelayMs: PropTypes.number,
|
||||||
|
defaultVisible: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Tooltip;
|
export default Tooltip;
|
||||||
|
@ -12,11 +12,13 @@ export type LogEntry = {
|
|||||||
export type State = {
|
export type State = {
|
||||||
opened: boolean;
|
opened: boolean;
|
||||||
entries: Array<LogEntry>;
|
entries: Array<LogEntry>;
|
||||||
|
copied: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
opened: false,
|
opened: false,
|
||||||
entries: [],
|
entries: [],
|
||||||
|
copied: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -32,6 +34,7 @@ export default (state: State = initialState, action: Action): State => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
opened: false,
|
opened: false,
|
||||||
|
copied: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
case LOG.ADD:
|
case LOG.ADD:
|
||||||
@ -40,6 +43,12 @@ export default (state: State = initialState, action: Action): State => {
|
|||||||
entries: state.entries.concat([action.payload]),
|
entries: state.entries.concat([action.payload]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case LOG.COPY_SUCCESS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
copied: true,
|
||||||
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user