Charge coin

This commit is contained in:
saplf
2019-09-03 21:05:19 +08:00
parent 1dc9a95835
commit da6d2c0e68
11 changed files with 388 additions and 23 deletions

View File

@@ -18,7 +18,9 @@
"bignumber.js": "^9.0.0", "bignumber.js": "^9.0.0",
"dva": "^2.6.0-beta.12", "dva": "^2.6.0-beta.12",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"qrcanvas-react": "^2.0.1",
"react": "^16.9.0", "react": "^16.9.0",
"react-clipboard.js": "^2.0.13",
"react-dom": "^16.9.0", "react-dom": "^16.9.0",
"react-fitted-image": "^1.0.1", "react-fitted-image": "^1.0.1",
"react-use": "^11.0.0", "react-use": "^11.0.0",

View File

@@ -19,6 +19,7 @@ export default {
'common.cancel': 'Cancel', 'common.cancel': 'Cancel',
'common.ok': 'Ok', 'common.ok': 'Ok',
'common.modify': 'Modify', 'common.modify': 'Modify',
'common.copied': '复制成功',
'check.login': 'Sign In', 'check.login': 'Sign In',
'check.register': 'Sign Up', 'check.register': 'Sign Up',
@@ -73,6 +74,12 @@ export default {
'estate.actualProfit': '实际收益', 'estate.actualProfit': '实际收益',
'estate.outTime': '卖出时间', 'estate.outTime': '卖出时间',
'mine.origin': '请选择来源币种',
'mine.calc': '汇率计算器:',
'mine.mine': '矿晶',
'mine.addressTitle': '充值 {label} 到您的专属地址,即可获得矿晶。扫描二维码或点击地址复制:',
'mine.info': '当你完成充值后,必须回到上一页矿场,点击刷新矿晶列表,平台查账确认后,您才能获赠矿晶。',
'profile.account': 'Account Settings', 'profile.account': 'Account Settings',
'profile.system': 'System Settings', 'profile.system': 'System Settings',
'profile.identity': '实名认证', 'profile.identity': '实名认证',

View File

@@ -19,6 +19,7 @@ export default {
'common.cancel': '取消', 'common.cancel': '取消',
'common.ok': '确定', 'common.ok': '确定',
'common.modify': '修改', 'common.modify': '修改',
'common.copied': '复制成功',
'check.login': '登录', 'check.login': '登录',
'check.register': '注册', 'check.register': '注册',
@@ -73,6 +74,12 @@ export default {
'estate.actualProfit': '实际收益', 'estate.actualProfit': '实际收益',
'estate.outTime': '卖出时间', 'estate.outTime': '卖出时间',
'mine.origin': '请选择来源币种',
'mine.calc': '汇率计算器:',
'mine.mine': '矿晶',
'mine.addressTitle': '充值 {label} 到您的专属地址,即可获得矿晶。扫描二维码或点击地址复制:',
'mine.info': '当你完成充值后,必须回到上一页矿场,点击刷新矿晶列表,平台查账确认后,您才能获赠矿晶。',
'profile.account': '账户管理', 'profile.account': '账户管理',
'profile.system': '系统设置', 'profile.system': '系统设置',
'profile.identity': '实名认证', 'profile.identity': '实名认证',

View File

@@ -1,7 +1,7 @@
import { Model } from 'dva'; import { Model } from 'dva';
import _ from 'lodash'; import _ from 'lodash';
import { getLocale, setLocale } from 'umi-plugin-locale' import { getLocale, setLocale } from 'umi-plugin-locale'
import { loadUser, storeUser, clearUser, clearMineList } from '@/utils/storage'; import { loadUser, storeUser, clearUser, clearMineList, clearCoins } from '@/utils/storage';
import { User } from '@/types/common'; import { User } from '@/types/common';
const initState = () => { const initState = () => {
@@ -46,6 +46,7 @@ const model: Model = {
*logout(_, { put, all }) { *logout(_, { put, all }) {
clearMineList(); clearMineList();
clearCoins();
yield all([ yield all([
put({ type: 'clearUser' }), put({ type: 'clearUser' }),
put({ type: 'home/clear' }), put({ type: 'home/clear' }),

View File

@@ -3,22 +3,103 @@
* Routes: * Routes:
* - ./src/pages/routes * - ./src/pages/routes
*/ */
import React, { useEffect } from 'react'; import React, { useEffect, useState } from 'react';
import { connect, DispatchProp } from 'dva'; import { connect, DispatchProp } from 'dva';
import { Spin, Tabs } from 'antd'; import { Spin, Input, Select, message } from 'antd';
import { formatMessage } from 'umi-plugin-locale'; import { formatMessage } from 'umi-plugin-locale';
import FittedImage from 'react-fitted-image'; import { QRCanvas } from 'qrcanvas-react';
import Clipboard from 'react-clipboard.js';
import { MineModelState } from './model'; import { MineModelState } from './model';
import { PageState, EstateType } from '@/types/common'; import { PageState } from '@/types/common';
import Header from '@/components/Header'; import Header from '@/components/Header';
import Info, { InfoItem } from '@/components/Info';
import Failure from '@/components/Failure';
import styles from './style.less'; import styles from './style.less';
const Option = Select.Option;
const MinePage: React.FC<DispatchProp & MineModelState> = ({ const MinePage: React.FC<DispatchProp & MineModelState> = ({
dispatch, dispatch,
pageState,
coin,
coins,
srcValue,
dstValue,
}) => { }) => {
useEffect(() => {
dispatch({ type: 'mine/load' });
}, []);
let body;
if (pageState === PageState.Pending) {
body = (
<Spin className={styles.none} />
);
} else if (pageState === PageState.Failure) {
body = (
<div className={styles.none}>{formatMessage({ id: 'common.loadError' })}</div>
);
} else if (pageState === PageState.Success) {
const onAddressCopied = () => {
message.success(formatMessage({ id: 'common.copied' }));
};
body = (
<>
<div className={styles.section}>
<div className="coin-selection">
<span>{formatMessage({ id: 'mine.origin' })}</span>
<Select
size="small"
value={coin && coin.id}
onChange={(payload: any) => dispatch({ type: 'mine/selectCoin', payload })}
>
{coins.map(it => (
<Option
key={it.id}
value={it.id}
>{it.label.toUpperCase()}</Option>
))}
</Select>
</div>
<div className="rate-trans">
<span>{formatMessage({ id: 'mine.calc' })}</span>
<Input
size="small"
value={srcValue}
onChange={e => dispatch({ type: 'mine/changeSrc', payload: e.target.value })}
/> {coin && coin.label.toUpperCase()} = {dstValue} {formatMessage({ id: 'mine.mine' })}
</div>
</div>
<div
className={`${styles.section} ${styles.main}`}
>
<div>{formatMessage({ id: 'mine.addressTitle' }, { label: coin && coin.label.toUpperCase() })}</div>
<Clipboard
component="div"
data-clipboard-text={coin && coin.address}
onSuccess={onAddressCopied}
>
<QRCanvas options={{
data: coin ? coin.address : '',
size: 240,
}} />
</Clipboard>
<Clipboard
component="div"
className="address"
data-clipboard-text={coin && coin.address}
onSuccess={onAddressCopied}
>
{coin && coin.address}
</Clipboard>
</div>
<div className={styles.section}>
<span>{formatMessage({ id: 'mine.info' })}</span>
</div>
</>
);
}
return ( return (
<div className={styles.container}> <div className={styles.container}>
@@ -26,6 +107,10 @@ const MinePage: React.FC<DispatchProp & MineModelState> = ({
className="header" className="header"
title={formatMessage({ id: 'home.mine.retrieve' })} title={formatMessage({ id: 'home.mine.retrieve' })}
/> />
<div className={styles.body}>
<div className={styles.card}>{body}</div>
</div>
</div> </div>
); );
}; };

View File

@@ -1,13 +1,24 @@
import { Model, routerRedux } from "dva"; import { Model, routerRedux } from "dva";
import _ from 'lodash';
import { message } from 'antd'; import { message } from 'antd';
import { Estate, PageState } from '@/types/common'; import { Estate, PageState, CoinUnion } from '@/types/common';
import { getEstateDetail } from './service'; import { getCoins, calcRate } from './service';
import { isDev } from '@/utils/utils'; import { isDev } from '@/utils/utils';
export interface MineModelState { export interface MineModelState {
coins: CoinUnion[];
pageState: PageState;
coin: CoinUnion | null;
srcValue: string;
dstValue: string;
} }
const initState: MineModelState = { const initState: MineModelState = {
coins: [],
coin: null,
pageState: PageState.Pending,
srcValue: '1',
dstValue: '1',
}; };
const model: Model = { const model: Model = {
@@ -16,6 +27,46 @@ const model: Model = {
state: initState, state: initState,
effects: { effects: {
*load(_, { put, call }) {
yield put({ type: 'onUpdateState', pageState: PageState.Pending });
try {
const coins: CoinUnion[] = yield call(getCoins);
const coin = coins[0];
yield put({
type: 'onUpdateState',
pageState: PageState.Success,
coins,
coin: coins[0],
srcValue: '1',
dstValue: calcRate('1', coin && coin.rate),
});
} catch (e) {
yield put({
type: 'onUpdateState',
pageState: PageState.Failure,
});
}
},
*selectCoin({ payload: id }, { put, select }) {
const { coins, srcValue } = yield select((state: any) => state.mine);
const coin = _.find(coins, ['id', id]);
yield put({
type: 'onUpdateState',
coin,
dstValue: calcRate(srcValue, coin && coin.rate),
});
},
*changeSrc({ payload }, { put, select }) {
if (isNaN(payload)) return;
const { coin } = yield select((state: any) => state.mine);
yield put({
type: 'onUpdateState',
srcValue: payload,
dstValue: calcRate(payload, coin && coin.rate),
});
},
}, },
reducers: { reducers: {

View File

@@ -1,18 +1,42 @@
import http from '@/utils/http'; import http from '@/utils/http';
import { Estate, EstateType } from '@/types/common'; import _ from 'lodash';
import BigNumber from 'bignumber.js';
import { Estate, EstateType, CoinUnion, CoinSupport, CoinAddress } from '@/types/common';
import { calcEstate } from '@/utils/transform'; import { calcEstate } from '@/utils/transform';
import { loadCoins, storeCoins } from '@/utils/storage';
export async function getEstateDetail(id: string) { export async function getCoins(): Promise<CoinUnion[]> {
const { const coinsCached = loadCoins();
ok, if (coinsCached && coinsCached.length) {
data, return coinsCached;
msg,
} = await http.get<Estate>('/estateorder/detail', { id });
if (ok && data) {
data.type = data.outTime ? EstateType.Sold : EstateType.Hold;
calcEstate(data);
return data;
} }
throw Error(msg); const [
{ ok: sOk, data: sData, msg: sMsg },
{ ok: aOk, data: aData, msg: aMsg },
] = await Promise.all([
http.get<CoinSupport[]>('/fund/coins'),
http.get<CoinAddress[]>('/fund/queryAddress'),
]);
if (!sOk || !sData) {
throw Error(sMsg);
}
if (!aOk || !aData) {
throw Error(aMsg);
}
const result = sData.map(it => Object.assign(
it,
_.find(aData, ['id', it.id]),
));
storeCoins(result);
return result;
}
export function calcRate(input: string, rate?: string): string {
if (!input || !rate) return '';
return new BigNumber(input).times(rate).decimalPlaces(2).toString();
} }

View File

@@ -5,6 +5,8 @@
height: 100%; height: 100%;
background: linear-gradient(to bottom, @purple-one, @purple-two); background: linear-gradient(to bottom, @purple-one, @purple-two);
position: relative; position: relative;
display: flex;
flex-direction: column;
:global { :global {
.header { .header {
@@ -13,3 +15,86 @@
} }
} }
} }
.body {
flex-grow: 1;
overflow: auto;
}
.none {
text-align: center;
width: 100%;
margin-top: 40%;
}
.card {
background-color: #fff;
margin: 10px;
box-shadow: 1px 1px 8px rgba(0, 0, 0, .2);
min-height: 60%;
}
.section {
@pLeft: 48px;
@pTop: 20px;
padding-left: @pLeft;
padding-right: 30px;
padding-top: @pTop;
position: relative;
&::before {
content: '';
display: block;
position: absolute;
@size: 10px;
width: @size;
height: @size;
background-color: @purple-two;
border-radius: @size / 2;
top: @pTop + @size / 2 + 2px;
left: @pLeft / 2 - @size / 2;
}
:global {
.coin-selection {
display: flex;
align-items: baseline;
.ant-select {
flex-grow: 1;
margin: 0 4px;
}
}
.rate-trans {
display: flex;
align-items: baseline;
padding: 4px 8px;
background-color: #eee3f9;
margin: 8px 0;
font-size: 0.8rem;
.ant-input {
width: 60px;
margin: 0 4px;
}
}
.address {
font-family: monospace;
word-break: break-all;
}
}
}
.main {
display: flex;
flex-direction: column;
align-items: center;
:global {
canvas {
margin: 10px 0;
}
}
}

View File

@@ -141,6 +141,20 @@ export interface Mine {
export type Mines = Mine[]; export type Mines = Mine[];
export interface CoinSupport {
id: string;
label: string;
rate: string;
}
export interface CoinAddress {
id: string;
label: string;
address: string;
}
export interface CoinUnion extends CoinSupport, CoinAddress {};
export enum MarketEstateAvailable { export enum MarketEstateAvailable {
No = 0, No = 0,
Yes = 1, Yes = 1,

View File

@@ -2,6 +2,7 @@
const userKey = 'user-key'; const userKey = 'user-key';
const areaCodeKey = 'area-code-key'; const areaCodeKey = 'area-code-key';
const mineListKey = 'mine-list-key'; const mineListKey = 'mine-list-key';
const coinsKey = 'coin-key';
// user info from now on // user info from now on
function storeUser(user: any = undefined) { function storeUser(user: any = undefined) {
@@ -54,6 +55,23 @@ function clearMineList() {
localStorage.removeItem(mineListKey); localStorage.removeItem(mineListKey);
} }
// coin list info from now on
function storeCoins(coins: any) {
localStorage.setItem(coinsKey, JSON.stringify(coins));
}
function loadCoins() {
try {
return JSON.parse(localStorage.getItem(coinsKey) || 'null');
} catch (e) {
return null;
}
}
function clearCoins() {
localStorage.removeItem(coinsKey);
}
export { export {
storeUser, storeUser,
loadUser, loadUser,
@@ -65,4 +83,8 @@ export {
storeMineList, storeMineList,
loadMineList, loadMineList,
clearMineList, clearMineList,
storeCoins,
loadCoins,
clearCoins,
} }

View File

@@ -1055,7 +1055,7 @@
dependencies: dependencies:
regenerator-runtime "^0.13.2" regenerator-runtime "^0.13.2"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5": "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5":
version "7.5.5" version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
@@ -1421,6 +1421,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/clipboard@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/clipboard/-/clipboard-2.0.1.tgz#75a74086c293d75b12bc93ff13bc7797fef05a40"
integrity sha512-gJJX9Jjdt3bIAePQRRjYWG20dIhAgEqonguyHxXuqALxsoDsDLimihqrSg8fXgVTJ4KZCzkfglKtwsh/8dLfbA==
"@types/eslint-visitor-keys@^1.0.0": "@types/eslint-visitor-keys@^1.0.0":
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
@@ -1599,7 +1604,7 @@
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
"@types/react@*", "@types/react@^16.9.2", "@types/react@~16.9.1": "@types/react@*", "@types/react@^16.8.17", "@types/react@^16.9.2", "@types/react@~16.9.1":
version "16.9.2" version "16.9.2"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.2.tgz#6d1765431a1ad1877979013906731aae373de268" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.2.tgz#6d1765431a1ad1877979013906731aae373de268"
integrity sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg== integrity sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==
@@ -3631,6 +3636,15 @@ cli-width@^2.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
clipboard@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d"
integrity sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
clipboardy@2.1.0: clipboardy@2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.1.0.tgz#0123a0c8fac92f256dc56335e0bb8be97a4909a5" resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.1.0.tgz#0123a0c8fac92f256dc56335e0bb8be97a4909a5"
@@ -4641,6 +4655,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
delegate@^3.1.2:
version "3.2.0"
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
delegates@^1.0.0: delegates@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
@@ -6747,6 +6766,13 @@ gonzales-pe@^4.2.3:
dependencies: dependencies:
minimist "1.1.x" minimist "1.1.x"
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=
dependencies:
delegate "^3.1.2"
got@9.6.0, got@^9.6.0: got@9.6.0, got@^9.6.0:
version "9.6.0" version "9.6.0"
resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
@@ -11636,6 +11662,28 @@ q@^1.1.2:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
qrcanvas-react@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/qrcanvas-react/-/qrcanvas-react-2.0.1.tgz#4cf8c0d0c8cb9c075bbc1fbd19d6bdf1e9919e46"
integrity sha512-mwcd9lcEXzFsMvrV/eKxYxCUdlv7gin8L0LZJ5R0nNXPLFndz1LAHa3dtPIvfBzwY6RhQoh1N74+ODZvEt4qJQ==
dependencies:
"@babel/runtime" "^7.4.4"
"@types/react" "^16.8.17"
qrcanvas "^3.0.4"
qrcanvas@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/qrcanvas/-/qrcanvas-3.0.4.tgz#f0fb400f31f148508f494fa49a29aa5b276d2dfe"
integrity sha512-aAafqeNTJVsWIc2vbqw/R+ByUUdmcncTpiy7eRq9vbcvzuhQZcK4IdfjVc4ey7nwBCncnraeYRZbnOecd1rDmw==
dependencies:
"@babel/runtime" "^7.4.4"
qrcode-generator "^1.4.3"
qrcode-generator@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/qrcode-generator/-/qrcode-generator-1.4.3.tgz#4876e8f280e65b6c94615f4c19c484f6b964b199"
integrity sha512-++rVRvMRq5BlHfmAafl8a4ppUntzUxCCUTT2t0siUgqKwdnqRzY8IH6f6WSX5dZUhD2Ul5/MIKuTJddflwrGzw==
qs@6.7.0: qs@6.7.0:
version "6.7.0" version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
@@ -12243,6 +12291,15 @@ rc@^1.2.7, rc@^1.2.8:
minimist "^1.2.0" minimist "^1.2.0"
strip-json-comments "~2.0.1" strip-json-comments "~2.0.1"
react-clipboard.js@^2.0.13:
version "2.0.13"
resolved "https://registry.yarnpkg.com/react-clipboard.js/-/react-clipboard.js-2.0.13.tgz#4430d4ef989c4c39303553c2c22f20b72b2d73dd"
integrity sha512-1tjFU52LbtETZe223bc/q9JnbguWXqrgWCHpnVWJ4YYhzoV62jJP0NghAYH6+F7G5SI80wnQHdBjgqppNTY7Xg==
dependencies:
"@types/clipboard" "^2.0.1"
clipboard "^2.0.0"
prop-types "^15.5.0"
react-dev-utils@9.0.1: react-dev-utils@9.0.1:
version "9.0.1" version "9.0.1"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.0.1.tgz#5c03d85a0b2537d0c46af7165c24a7dfb274bef2" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.0.1.tgz#5c03d85a0b2537d0c46af7165c24a7dfb274bef2"
@@ -13367,6 +13424,11 @@ select-hose@^2.0.0:
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
select@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
selfsigned@^1.9.1: selfsigned@^1.9.1:
version "1.10.4" version "1.10.4"
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.4.tgz#cdd7eccfca4ed7635d47a08bf2d5d3074092e2cd" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.4.tgz#cdd7eccfca4ed7635d47a08bf2d5d3074092e2cd"
@@ -14586,6 +14648,11 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiny-emitter@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tiny-invariant@^1.0.2: tiny-invariant@^1.0.2:
version "1.0.6" version "1.0.6"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73"