react-use#useEffectOnce TypeScript Examples
The following examples show how to use
react-use#useEffectOnce.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: timeSelector.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
TimeSelector = (props: IProps) => {
const { defaultTime, onChangeTime, timeSpan, className, inline } = props;
const { hours } = timeSpan;
const styleName = inline ? 'monitor-time-selector-inline' : 'monitor-time-selector';
useEffectOnce(() => {
if (defaultTime) {
onChangeTime(defaultTime);
} else {
onChangeTime(timeSpan.hours);
}
});
const handleChangeTime = (val: number) => {
props.onChangeTime(val);
};
return (
<div className={`${className} ${styleName}`}>
<Select
key="select"
className="time-range-selector"
defaultValue={(defaultTime || hours) && `${defaultTime || hours}`}
onChange={handleChangeTime}
>
{map(timeSelectorPlan, (value, key) => {
return (
<Select.Option key={value} value={key}>
{value}
</Select.Option>
);
})}
</Select>
</div>
);
}
Example #2
Source File: BaseProviders.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 6 votes |
BaseProviders: FC = ({ children }) => {
useEffectOnce(() => {
// Redirect for legacy links (without hash)
if (window.location.pathname !== '/' && !window.location.pathname.startsWith('/ipfs/')) {
window.location.hash = window.location.pathname
window.location.pathname = ''
}
})
return (
<BaseCtxProvider>
<HashRouter>
<Providers>
<Updaters />
{children}
</Providers>
</HashRouter>
</BaseCtxProvider>
)
}
Example #3
Source File: index.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
MSComponentInfo = () => {
const infoList = mspInfoStore.useStore((s) => s.infoList);
const { getMSComponentInfo } = mspInfoStore.effects;
const { clearMSComponentInfo } = mspInfoStore.reducers;
const [loading] = useLoading(mspInfoStore, ['getMSComponentInfo']);
const insId = routeInfoStore.useStore((s) => s.params.insId);
useEffectOnce(() => {
getMSComponentInfo();
return clearMSComponentInfo;
});
const dataSource = infoList.map((info) => {
return {
tabTitle: isZh() ? info.cnName : info.enName,
tabKey: info.addonName,
content: <PureAddonSettings insId={insId} addonConfig={info} isFetching={loading} />,
};
});
return (
<>
<SettingTabs dataSource={dataSource} />
<Copy selector=".cursor-copy" />
</>
);
}
Example #4
Source File: GasStation.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 5 votes |
GasStation: FC = () => {
const networkPrices = useNetworkPrices()
const { gasLimit, gasPrice, setGasPrice } = useGas()
const [gasPriceType, setGasPriceType] = useState<GasPriceType>(GasPriceType.Standard)
const customTransactionFee =
gasPriceType === GasPriceType.Custom && gasPrice && networkPrices.value?.nativeToken && gasLimit
? (gasPrice / 1e9) * (networkPrices.value.nativeToken / 1e9) * gasLimit.toNumber()
: undefined
const handleChange = useCallback<ChangeEventHandler<HTMLInputElement>>(
event => {
setGasPrice(parseFloat(event.target.value) * 1e9)
},
[setGasPrice],
)
useEffectOnce(() => {
setGasPrice((networkPrices.value?.gas?.[gasPriceType as 'fast'] ?? 0) * 1e9)
})
return (
<Container>
{OPTIONS.map(({ type, label }) => {
const _gasPrice = networkPrices.value?.gas?.[type as 'fast']
const transactionFee =
_gasPrice && networkPrices.value?.nativeToken && gasLimit
? _gasPrice * (networkPrices.value?.nativeToken / 1e9) * gasLimit.toNumber()
: undefined
const selected = type === gasPriceType
return (
<Option key={type}>
<OptionButton
highlighted={selected}
onClick={() => {
setGasPrice((_gasPrice as number) * 1e9)
setGasPriceType(type)
}}
>
{label}
</OptionButton>
<div>
{type === GasPriceType.Custom ? (
<div>
<Input disabled={type !== gasPriceType} placeholder="10" onChange={handleChange} />
<Fee>{customTransactionFee ? `$${customTransactionFee.toFixed(2)}` : '$–'}</Fee>
</div>
) : (
<div>
<Price>{_gasPrice?.toFixed(0)}</Price>
<Fee>{transactionFee ? `$${transactionFee.toFixed(2)}` : '–'}</Fee>
</div>
)}
</div>
</Option>
)
})}
</Container>
)
}
Example #5
Source File: AppWrapper.tsx From flood with GNU General Public License v3.0 | 5 votes |
AppWrapper: FC<AppWrapperProps> = observer(({children, className}: AppWrapperProps) => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
useEffectOnce(() => {
AuthActions.verify().then(
({initialUser}: {initialUser?: boolean}): void => {
if (initialUser) {
navigate('/register', {replace: true});
} else {
navigate('/overview', {replace: true});
}
},
(): void => {
navigate('/login', {replace: true});
},
);
});
if (searchParams.has('action')) {
if (searchParams.get('action') === 'add-urls') {
if (searchParams.has('url')) {
UIStore.setActiveModal({
id: 'add-torrents',
tab: 'by-url',
urls: [{id: 0, value: searchParams.get('url') as string}],
});
}
}
}
let overlay: ReactNode = null;
if (!AuthStore.isAuthenticating || (AuthStore.isAuthenticated && !UIStore.haveUIDependenciesResolved)) {
overlay = <LoadingOverlay dependencies={UIStore.dependencies} />;
}
if (AuthStore.isAuthenticated && !ClientStatusStore.isConnected && ConfigStore.authMethod !== 'none') {
overlay = (
<div className="application__loading-overlay">
<div className="application__entry-barrier">
<LogoutButton className={css({position: 'absolute', left: '5px', top: '5px'})} />
<ClientConnectionInterruption />
</div>
</div>
);
}
return (
<div className={classnames('application', className)}>
<WindowTitle />
<TransitionGroup>
{overlay != null ? (
<CSSTransition timeout={{enter: 1000, exit: 1000}} classNames="application__loading-overlay">
{overlay}
</CSSTransition>
) : null}
</TransitionGroup>
{children}
</div>
);
})
Example #6
Source File: index.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 5 votes |
ProtocolRoutes: FC = () => {
const { supportedMassets } = useNetwork()
const [massetName] = useSelectedMasset()
const history = useHistory()
useEffectOnce(() => {
if (supportedMassets.includes(massetName)) return
// Redirect if not supported masset
const tab = window.location.hash.split('/')?.[2]
if (tab) history.push(`/musd/${tab}`)
})
return (
<Switch>
<Route exact path="/:massetName/earn" component={EarnRedirect} />
<Route exact path="/:massetName/earn/admin" component={EarnRedirect} />
<Route exact path="/:massetName/earn/:slugOrAddress" component={EarnRedirect} />
<Route exact path="/:massetName/earn/:slugOrAddress/:userAddress" component={EarnRedirect} />
<Route exact path="/:massetName/stats" component={Stats} />
<Route exact path="/:massetName/save" component={Save} />
<Route exact path="/:massetName/pools" component={Pools} />
<Route exact path="/:massetName/swap" component={Exchange} />
<Route exact path="/:massetName/pools/:poolAddress" component={PoolDetail} />
<Route exact path="/" component={Dashboard} />
<Redirect exact path="/analytics" to="/musd/stats" />
<Redirect exact path="/save" to="/musd/save" />
<Redirect exact path="/earn" to="/musd/earn" />
<Redirect exact path="/mint" to="/musd/swap/mint" />
<Redirect exact path="/redeem" to="/musd/swap/redeem" />
<Redirect exact path="/swap" to="/musd/swap/" />
<Redirect exact path="/musd" to="/musd/swap/" />
<Redirect exact path="/mbtc" to="/mbtc/swap/" />
<Redirect exact path="/musd/forge/*" to="/musd/swap/" />
<Redirect exact path="/mbtc/forge/*" to="/mbtc/swap/" />
<Redirect exact path="/musd/exchange/*" to="/musd/swap/" />
<Redirect exact path="/mbtc/exchange/*" to="/mbtc/swap/" />
<Redirect exact path="/musd/analytics" to="/musd/stats" />
<Redirect exact path="/mbtc/analytics" to="/mbtc/stats" />
<Route component={NotFound} />
</Switch>
)
}
Example #7
Source File: config-env-selector.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
ConfigEnvSelector = (props: IProps) => {
const { onTest, scope, canRunTest } = props;
const scopeConfigData = scopeConfig[scope];
const [caseDetail, configEnvs] = autoTestStore.useStore((s) => [s.caseDetail, s.configEnvs]);
const { id: orgId, name: orgName } = orgStore.useStore((s) => s.currentOrg);
const projectId = routeInfoStore.useStore((s) => s.params.projectId);
const { getAutoTestConfigEnv, clearConfigEnvs, getCaseDetail } = autoTestStore;
const info = projectStore.useStore((s) => s.info);
const { clusterConfig, name: projectName } = info;
const [{ formVis, fields, inParamsForm, canDoTest, needModal, clusterList }, updater, update] = useUpdate({
formVis: false,
fields: [] as any[],
inParamsForm: [] as any[],
canDoTest: false,
needModal: true,
clusterList: [],
});
useEffectOnce(() => {
scopeConfigData.executeEnvChosen && getAutoTestConfigEnv({ scopeID: projectId, scope: scopeConfigData.scope });
return () => clearConfigEnvs();
});
const setFields = (_inParamsForm: any[]) => {
const _f = [
...insertWhen(scopeConfigData.executeClusterChosen, [
{
label: i18n.t('choose cluster'),
component: 'select',
required: true,
key: 'clusterName',
defaultValue: getLastRunParams().clusterName || 'TEST',
type: 'select',
dataSource: {
type: 'static',
static: map(clusterList, (item) => ({ name: item.workspace, value: item.key })),
},
},
]),
...insertWhen(scopeConfigData.executeEnvChosen, [
{
label: i18n.t('choose global configuration'),
component: 'select',
required: true,
key: 'configManageNamespaces',
defaultValue: '0',
type: 'select',
dataSource: {
type: 'static',
static: map([{ ns: '0', displayName: i18n.t('None') }, ...configEnvs], (item) => ({
name: item.displayName,
value: item.ns,
})),
},
},
]),
...insertWhen(!isEmpty(_inParamsForm), [
{
component: 'custom',
getComp: () => {
return <div className="font-medium border-bottom">{i18n.t('dop:Inputs')}</div>;
},
},
..._inParamsForm,
]),
];
return _f;
};
React.useEffect(() => {
updater.fields(setFields(inParamsForm));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [inParamsForm, clusterConfig]);
const inFormProps = React.useMemo(() => {
inParamsKey += 1;
return { fieldList: fields, key: inParamsKey };
}, [fields]);
const getLastRunParams = () => {
const runParams = get(caseDetail, 'meta.runParams');
const val: Obj = {};
map(runParams, (item) => {
val[item.name] = item.value;
});
return val;
};
const onClickTest = () => {
if (!needModal) {
// 无需弹框,直接执行
execute();
return;
}
if (canDoTest) {
updater.formVis(true);
} else {
const ymlStr = get(caseDetail, 'meta.pipelineYml');
updater.canDoTest(false);
if (ymlStr) {
(parsePipelineYmlStructure({ pipelineYmlContent: ymlStr }) as unknown as Promise<any>)
.then((res: any) => {
const updateObj = {} as any;
if (!isEmpty(res.data.stages)) {
updateObj.canDoTest = true;
updateObj.formVis = true;
} else {
notify('warning', i18n.t('dop:please add valid tasks to the pipeline below before operating'));
}
const inP = ymlDataToFormData(get(res, 'data.params') || [], getLastRunParams());
if (isEmpty(inP) && !scopeConfigData.executeEnvChosen && !scopeConfigData.executeClusterChosen) {
// 无入参,无环境,不需要弹框
updateObj.needModal = false;
updateObj.formVis = false;
} else {
updateObj.inParamsForm = inP;
}
update(updateObj);
if (updateObj.needModal === false) execute();
})
.catch(() => {
notify('warning', i18n.t('dop:please add valid tasks to the pipeline below before operating'));
});
} else {
notify('warning', i18n.t('dop:please add valid tasks to the pipeline below before operating'));
}
}
};
React.useEffect(() => {
updater.canDoTest(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [caseDetail]);
React.useEffect(() => {
if (!isEmpty(clusterConfig)) {
const sortBy = WORKSPACE_LIST;
const clusterData = [] as any[];
sortBy.forEach((workspace) => {
if (clusterConfig[workspace]) {
clusterData.push({
workspace: workSpaceMap[workspace],
clusterName: clusterConfig[workspace],
key: workspace,
});
}
});
updater.clusterList(clusterData);
}
}, [clusterConfig, updater]);
const execute = (p: Obj = {}) => {
let curClusterName = clusterConfig?.TEST;
const chosenCluster = find(p?.runParams, { name: 'clusterName' });
if (chosenCluster) {
curClusterName = clusterConfig[chosenCluster.value];
}
createPipelineAndRun({
pipelineYml: get(caseDetail, 'meta.pipelineYml'),
pipelineSource: scopeConfigData.runPipelineSource,
pipelineYmlName: caseDetail.inode,
clusterName: curClusterName,
autoRunAtOnce: true,
autoStartCron: true,
labels: { orgID: `${orgId}`, projectID: projectId, projectName, orgName },
...p,
}).then((res: any) => {
onTest(res.data);
});
};
const saveRunParams = (runParams: any[]) => {
updateCasePipeline({ nodeId: caseDetail.inode, runParams }).then(() => {
getCaseDetail({ id: caseDetail.inode });
});
};
return (
<div>
<Tooltip title={canRunTest ? '' : i18n.t('dop:pipeline-run-tip')}>
<Button
type="primary"
disabled={!canRunTest}
onClick={(e) => {
e.stopPropagation();
onClickTest();
}}
>
{scopeConfigData.text.executeButton}
</Button>
</Tooltip>
<FormModal
title={i18n.t('Execute')}
onCancel={() => updater.formVis(false)}
onOk={(val: any) => {
const { configManageNamespaces, ...rest } = val;
const runParams = isEmpty(rest) ? [] : map(rest, (v, k) => ({ name: k, value: v }));
saveRunParams(runParams); // 保存此次的值
execute({
configManageNamespaces: configManageNamespaces === '0' ? [] : [configManageNamespaces],
runParams,
});
}}
visible={formVis}
{...inFormProps}
/>
</div>
);
}
Example #8
Source File: FraxStakingProvider.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 4 votes |
FraxStakingProvider: FC = ({ children }) => {
const addresses = useNetworkAddresses()
const fraxAddresses = (addresses as MaticMainnet['addresses'])['FRAX']
const signerOrProvider = useSignerOrProvider()
const blockNumber = useBlockNow()
const account = useAccount()
const stakingContract = useRef<FraxCrossChainFarm>()
const feederPool = useRef<ERC20>()
const [staticData, setStaticData] = useFetchState<StaticData>()
const [subscribedData, setSubscribedData] = useFetchState<SubscribedData>()
const [rewards, setRewards] = useFetchState<BoostedAPY>()
// Set/reset on network/signer change
useEffect(() => {
if (fraxAddresses && signerOrProvider) {
stakingContract.current = FraxCrossChainFarm__factory.connect(fraxAddresses.stakingContract, signerOrProvider)
feederPool.current = ERC20__factory.connect(fraxAddresses.feederPool, signerOrProvider)
} else {
stakingContract.current = undefined
feederPool.current = undefined
setStaticData.value()
setSubscribedData.value()
}
}, [fraxAddresses, signerOrProvider, setStaticData, setSubscribedData])
// Frax API call for rewards APYs
useEffectOnce(() => {
setRewards.fetching()
fetch('https://api.frax.finance/pools')
.then(res => {
res
.json()
.then((json: { identifier: string; pairLink: string; apy?: string; apy_max?: string }[]) => {
const poolData = json.find(p => p.identifier === 'mStable FRAX/mUSD')
if (poolData) {
setRewards.value({
base: parseFloat(poolData.apy ?? '0'),
maxBoost: parseFloat(poolData.apy_max ?? '0'),
userBoost: 0,
})
}
})
.catch(setRewards.error)
})
.catch(setRewards.error)
})
// Initial contract calls (once only)
useEffect(() => {
if (!stakingContract.current || staticData.fetching || staticData.value) return
setStaticData.fetching()
Promise.all([
stakingContract.current.lock_max_multiplier(),
stakingContract.current.lock_time_for_max_multiplier(),
stakingContract.current.lock_time_min(),
])
.then(([lockMaxMultiplier, lockTimeMax, lockTimeMin]) => {
if (!stakingContract.current) return
setStaticData.value({
lockMaxMultiplier: parseFloat(lockMaxMultiplier.toString()) / 1e18,
lockTimeMax: parseInt(lockTimeMax.toString()),
lockTimeMin: parseInt(lockTimeMin.toString()),
})
})
.catch(setStaticData.error)
}, [setStaticData, staticData.fetching, staticData.value, fraxAddresses])
// Contract calls on every block
useEffect(() => {
if (!fraxAddresses || !stakingContract.current || subscribedData.fetching) return
Promise.all([
account
? Promise.all([
stakingContract.current.earned(account),
stakingContract.current.combinedWeightOf(account),
stakingContract.current.lockedStakesOf(account),
stakingContract.current.lockedLiquidityOf(account),
feederPool.current.balanceOf(account),
])
: undefined,
])
.then(([[earned, combinedWeight, lockedStakes, lockedLiquidity, poolBalance] = []]) => {
let accountData: SubscribedData['accountData']
if (earned && combinedWeight && lockedStakes && lockedLiquidity) {
accountData = {
earned: earned.map((amount, index) => {
const address = index === 0 ? fraxAddresses.rewardsTokens[0] : fraxAddresses.rewardsTokens[1]
return {
address,
symbol: address === fraxAddresses.rewardsTokens[0] ? 'FXS' : 'MTA',
amount: new BigDecimal(amount), // Assumed 18 decimals (so far, we know it will be)
}
}),
combinedWeight: new BigDecimal(combinedWeight),
lockedLiquidity: new BigDecimal(lockedLiquidity),
lockedStakes: lockedStakes.map(({ kek_id, start_timestamp, ending_timestamp, liquidity, lock_multiplier }) => ({
kekId: kek_id,
startTime: new Date(parseInt(start_timestamp.toString())).getTime() * 1000, // ms
endTime: new Date(parseInt(ending_timestamp.toString())).getTime() * 1000,
liquidity: new BigDecimal(liquidity),
lockMultiplier: new BigDecimal(lock_multiplier),
})),
poolBalance: new BigDecimal(poolBalance),
}
}
setSubscribedData.value({ accountData, lastUpdate: blockNumber })
})
.catch(setSubscribedData.error)
}, [blockNumber, account, setSubscribedData, fraxAddresses, subscribedData.fetching])
return (
<contractCtx.Provider value={stakingContract.current}>
<stateCtx.Provider
value={useMemo(
() => ({
staticData,
subscribedData,
rewards,
}),
[rewards, staticData, subscribedData],
)}
>
{children}
</stateCtx.Provider>
</contractCtx.Provider>
)
}
Example #9
Source File: issue-field-setting-modal.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
IssueFieldSettingModal = ({ visible, issueType = 'EPIC', closeModal }: IProps) => {
const { addFieldItem, batchUpdateFieldsOrder, deleteFieldItem, getFieldsByIssue } = issueFieldStore.effects;
const [fieldList] = issueFieldStore.useStore((s) => [s.fieldList]);
const { clearFieldList } = issueFieldStore.reducers;
const { id: orgID } = orgStore.useStore((s) => s.currentOrg);
const [{ selectedField, filedOptions }, updater, update] = useUpdate({
selectedField: {} as ISSUE_FIELD.IFiledItem,
filedOptions: [] as ISSUE_FIELD.IFiledItem[],
});
useEffectOnce(() => {
getFieldOptions({ propertyIssueType: 'COMMON', orgID }).then(({ data }) => {
updater.filedOptions(data || []);
});
});
const onAddField = React.useCallback(async () => {
const params = {
...selectedField,
propertyIssueType: issueType,
relation: selectedField.propertyID,
} as Omit<ISSUE_FIELD.IFiledItem, 'propertyID' | 'index'>;
await addFieldItem(params);
update({ selectedField: undefined });
getFieldsByIssue({ propertyIssueType: issueType, orgID });
}, [addFieldItem, getFieldsByIssue, issueType, orgID, selectedField, update]);
const onCloseModal = () => {
closeModal();
update({ selectedField: undefined });
clearFieldList();
};
const changePos = React.useCallback(
async (index: number, direction: number) => {
if (fieldList.length > 1) {
const tempList = produce(fieldList, (draft) => {
if (direction < 0 && index > 0) {
draft[index - 1].index = index;
draft[index].index = index - 1;
} else {
draft[index].index = index + 1;
draft[index + 1].index = index;
}
});
await batchUpdateFieldsOrder(tempList);
getFieldsByIssue({ propertyIssueType: issueType, orgID });
}
},
[batchUpdateFieldsOrder, fieldList, getFieldsByIssue, issueType, orgID],
);
const onDelete = React.useCallback(
async (propertyID) => {
await deleteFieldItem({ propertyID });
getFieldsByIssue({ propertyIssueType: issueType, orgID });
},
[deleteFieldItem, getFieldsByIssue, issueType, orgID],
);
const renderFieldItem = ({ displayName, propertyType }: { displayName: string; propertyType: string }) => (
<>
<div className="nowrap field-label">{displayName}</div>
<div className="">
<IssueIcon type={propertyType} withName />
</div>
</>
);
const renderDefaultContent = React.useMemo(
() =>
map(DEFAULT_ISSUE_FIELDS_MAP[issueType], ({ propertyName, displayName, propertyType }) => {
return <div key={propertyName}>{renderFieldItem({ displayName, propertyType })}</div>;
}),
[issueType],
);
const renderCustomFields = React.useCallback(
() =>
map(fieldList, ({ propertyName, propertyID, propertyType, displayName }, index) => {
const isFirst = index === 0;
const isLast = index === fieldList.length - 1;
return (
<div className="panel" key={propertyName}>
<div className="border-bottom px-4 py-2">
<div className="flex justify-between items-center">
<div className="nowrap flex items-center justify-start">
{renderFieldItem({ displayName, propertyType })}
</div>
<div className="table-operations">
<Popconfirm
title={`${i18n.t('dop:confirm to remove the quote?')}`}
onConfirm={() => {
onDelete(propertyID);
}}
>
<span className="table-operations-btn">{i18n.t('Remove')}</span>
</Popconfirm>
<span
className={`table-operations-btn ${isFirst ? 'disabled' : ''}`}
onClick={() => !isFirst && changePos(index, -1)}
>
{i18n.t('Move up')}
</span>
<span
className={`table-operations-btn ${isLast ? 'disabled' : ''}`}
onClick={() => !isLast && changePos(index, 1)}
>
{i18n.t('Move down')}
</span>
</div>
</div>
</div>
</div>
);
}),
[changePos, fieldList, onDelete],
);
return (
<Modal
title={i18n.t('Edit') + FIELD_TYPE_ICON_MAP[issueType]?.name + i18n.t('Field')}
visible={visible}
onOk={onCloseModal}
width="660px"
onCancel={onCloseModal}
destroyOnClose
maskClosable={false}
footer={[
<Button type="primary" key="back" onClick={onCloseModal}>
{i18n.t('close')}
</Button>,
]}
>
<div className="issue-field-layout">
<div className="default-field-panel">
<div className="name">{i18n.t('dop:default field')}</div>
<div className="field-grid mb-4 pl-2">{renderDefaultContent}</div>
</div>
<div className="custom-field-panel">
<div className="name">{i18n.t('dop:custom fields')}</div>
<div className="custom-field-list">{renderCustomFields()}</div>
<div className="create-field-form mt-3">
<div className="flex justify-between items-center">
<Select
className="flex-1 mr-2"
value={selectedField?.propertyID}
placeholder={i18n.t('please choose the {name}', { name: i18n.t('dop:custom fields') })}
onChange={(e: any) => {
const selectedFieldItem = find(filedOptions, (t) => t.propertyID === e) as ISSUE_FIELD.IFiledItem;
updater.selectedField(selectedFieldItem);
}}
>
{map(filedOptions, ({ propertyID, propertyName }) => {
return (
<Option value={propertyID} key={propertyID}>
{propertyName}
</Option>
);
})}
</Select>
<div>
<Button type="primary" disabled={isEmpty(selectedField)} className="mr-2" onClick={onAddField}>
{i18n.t('dop:reference')}
</Button>
</div>
</div>
</div>
</div>
</div>
</Modal>
);
}
Example #10
Source File: AccountProvider.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 4 votes |
OnboardProvider: FC<{
chainId: ChainIds
}> = ({ children, chainId }) => {
const [address, setAddress] = useState<string | undefined>(undefined)
const [ensName, setEnsName] = useState<string | undefined>(undefined)
const [ensAvatar, setEnsAvatar] = useState<string | undefined>(undefined)
const [balance, setBalance] = useState<string | undefined>(undefined)
const [connected, setConnected] = useState<boolean>(false)
const [wallet, setWallet] = useState<Wallet | undefined>(undefined)
const [, setStakeSignatures] = useStakeSignatures()
const [{ appName }] = useBaseCtx()
const [, setInjectedChainId] = useInjectedChainIdCtx()
const [injectedProvider, setInjectedProvider] = useInjectedProviderCtx()
const network = useNetwork()
const rpcUrl = network.rpcEndpoints[0]
const isGovernance = appName === APP_NAME.GOVERNANCE
const onboard = useMemo(
() =>
Onboard({
hideBranding: true,
networkId: parseInt(isNaN(chainId) ? '1' : (chainId as unknown as string)),
subscriptions: {
address: account => {
if (account) {
setAddress(account.toLowerCase())
}
},
ens: ens => {
setEnsName(ens?.name)
},
network: setInjectedChainId,
balance: setBalance,
wallet: walletInstance => {
if (!walletInstance.provider) {
setWallet(undefined)
setInjectedProvider(undefined)
setConnected(false)
setAddress(undefined)
setEnsName(undefined)
setEnsAvatar(undefined)
return
}
setWallet(walletInstance)
const ethersProvider = new ethers.providers.Web3Provider(walletInstance.provider, 'any')
setInjectedProvider(ethersProvider as never)
setConnected(true)
if (walletInstance.name) {
localStorage.setItem('walletName', walletInstance.name)
} else {
localStorage.removeItem('walletName')
}
},
},
walletSelect: {
agreement: {
version: '0.1.0',
termsUrl: 'https://docs.mstable.org/advanced/app-usage-terms-and-conditions',
},
wallets: [
{
walletName: 'metamask',
preferred: true,
},
{
walletName: 'walletConnect',
rpc: {
[chainId]: rpcUrl,
},
preferred: true,
},
{
walletName: 'ledger',
rpcUrl,
preferred: true,
},
{
walletName: 'trezor',
appUrl: window.location.hostname,
email: '[email protected]',
rpcUrl,
preferred: true,
},
{ walletName: 'tally' },
{ walletName: 'xdefi' },
{ walletName: 'trust', rpcUrl },
{ walletName: 'gnosis', preferred: true },
{
walletName: 'lattice',
rpcUrl,
appName: 'mStable',
},
{
walletName: 'fortmatic',
apiKey: 'pk_live_262AEBF77922D028',
},
{
walletName: 'portis',
apiKey: 'bd88165a-43d7-481f-91bb-7e2f21e95ce6',
},
{ walletName: 'authereum' },
{ walletName: 'opera' },
{ walletName: 'operaTouch' },
{ walletName: 'torus' },
{ walletName: 'status' },
{ walletName: 'walletLink', rpcUrl, appName: 'mStable', preferred: true },
{ walletName: 'imToken', rpcUrl },
{ walletName: 'meetone' },
{ walletName: 'mykey', rpcUrl },
{ walletName: 'huobiwallet', rpcUrl },
{ walletName: 'hyperpay' },
{ walletName: 'wallet.io', rpcUrl },
],
},
walletCheck: [{ checkName: 'derivationPath' }, { checkName: 'connect' }, { checkName: 'accounts' }, { checkName: 'network' }],
}),
[chainId, rpcUrl, setInjectedChainId, setInjectedProvider],
)
const connect = useCallback(
async (walletName?: string) => {
try {
const selected = await onboard.walletSelect(walletName)
if (selected) {
const checked = await onboard.walletCheck()
if (!checked) return
setConnected(true)
if (walletName) localStorage.setItem('walletName', walletName)
return
}
} catch (error) {
console.error(error)
return
}
localStorage.removeItem('walletName')
onboard.walletReset()
setConnected(false)
setWallet(undefined)
setInjectedProvider(undefined)
},
[onboard, setInjectedProvider],
)
const reset = useCallback(() => {
onboard.walletReset()
localStorage.removeItem('walletName')
setWallet(undefined)
setConnected(false)
setInjectedProvider(undefined)
}, [onboard, setInjectedProvider])
useEffectOnce(() => {
const previouslySelectedWallet = localStorage.getItem('walletName')
if (previouslySelectedWallet && onboard.walletSelect) {
connect(previouslySelectedWallet).catch(error => {
console.error(error)
})
}
if (isGovernance) {
fetch(`${API_ENDPOINT}/signature`)
.then(resp => resp.json())
.then(json => {
setStakeSignatures(prevSignatures => ({
...prevSignatures,
message: json.message,
}))
})
.catch(console.error)
}
})
useEffect(() => {
if (!address || !isGovernance) return
fetch(`${API_ENDPOINT}/signature/${address}`)
.then(resp => resp.json())
.then(json => {
if (json.error) return
setStakeSignatures(prevSignatures => {
// TODO: I'm getting a weird race condition here with the library, this fix the issue
const prevHack = {
...JSON.parse(localStorage.getItem('stakeSignatures') || '{}'),
...prevSignatures,
}
return {
...prevHack,
[address]: json.signature,
}
})
})
.catch(console.warn)
}, [address, setStakeSignatures, isGovernance])
useEffect(() => {
if (!ensName || !injectedProvider) {
setEnsAvatar(undefined)
return
}
injectedProvider
.getAvatar(ensName)
.then(result => setEnsAvatar(result ?? undefined))
.catch(console.error)
}, [ensName, injectedProvider])
return (
<onboardCtx.Provider
value={useMemo(
() => ({
onboard,
address,
ensName,
ensAvatar,
balance,
wallet,
connected,
connect,
reset,
}),
[onboard, address, ensName, ensAvatar, balance, wallet, connected, connect, reset],
)}
>
{children}
</onboardCtx.Provider>
)
}
Example #11
Source File: [dataRequestId].tsx From rcvr-app with GNU Affero General Public License v3.0 | 4 votes |
DataRequestPage: React.FC<WithOwnerProps> = ({ owner }) => {
const { t } = usePageLocale(
'business/company/[companyId]/data-request/[dataRequestId]'
)
const { query } = useRouter()
const companyId = query.companyId.toString()
const dataRequestId = query.dataRequestId.toString()
const { data: company } = useCompany(companyId)
const { data: dataRequest, status } = useDataRequest(companyId, dataRequestId)
const [loading, setLoading] = React.useState(false)
const { modals, openModal } = useModals({
privateKey: PrivateKeyModal,
success: RedirectModal,
})
const headerMessages = React.useMemo(
() => ({
headerFrom: t('headerFrom'),
headerName: t('headerName'),
headerPhone: t('headerPhone'),
headerUntil: t('headerUntil'),
headerLeftAt: t('headerLeftAt'),
headerAddress: t('headerAddress'),
headerAreaName: t('headerAreaName'),
headerEnteredAt: t('headerEnteredAt'),
headerResidents: t('headerResidents'),
headerProvidedHealthDocument: t('headerProvidedHealthDocument'),
}),
[t]
)
const downloadFileLocales: DownloadFileLocales = React.useMemo(
() => ({
tested: t('tested'),
vaccinated: t('vaccinated'),
recovering: t('recovering'),
contactData: t('contactData'),
customerContactData: t('customerContactData'),
customerContactDataFrom: t('customerContactDataFrom'),
...headerMessages,
}),
[t, headerMessages]
)
const {
headerName,
headerFrom,
headerUntil,
headerPhone,
headerAddress,
headerAreaName,
headerResidents,
headerProvidedHealthDocument,
} = headerMessages
useEffectOnce(() => {
if (!owner.privateKey) {
openModal('privateKey', { ownerId: owner.id })
}
})
const handleEnterKey = React.useCallback(() => {
openModal('privateKey', { ownerId: owner.id })
}, [openModal, owner])
const { tickets, successCount, errorCount, pendingCount } =
React.useMemo(() => {
const encryptedTickets = dataRequest?.tickets || []
const { publicKey, privateKey } = owner
return decryptTickets(encryptedTickets, publicKey, privateKey)
}, [dataRequest, owner])
const handleDownload = React.useCallback(async () => {
setLoading(true)
const rows = ticketsToExcel(company, tickets, downloadFileLocales)
// generate xlsx
const { writeFile, utils: xlsx } = await import('xlsx')
const book = xlsx.book_new()
const sheet = xlsx.json_to_sheet(rows, { skipHeader: true })
const colWidths = [20, 20, 10, 20, 30, 15]
if (isCareEnv) colWidths.push(20)
sheet['!cols'] = colWidths.map((wch) => ({ wch }))
const date = formatDate(dataRequest.from, 'DD.MM')
const sheetname = date
xlsx.book_append_sheet(book, sheet, sheetname)
writeFile(
book,
`${downloadFileLocales.contactData} ${company?.name} ${date}.xlsx`
)
setLoading(false)
}, [tickets, company, dataRequest, downloadFileLocales])
const dateRange =
dataRequest?.from && dataRequest?.to
? formatDate(dataRequest.from, 'DD.MM.YYYY HH:mm') +
' – ' +
formatDate(dataRequest.to, 'DD.MM.YYYY HH:mm')
: ''
const title = dateRange
? `${downloadFileLocales.customerContactDataFrom} ${dateRange}`
: downloadFileLocales.customerContactData
const didDecrypt = dataRequest?.tickets && pendingCount === 0
const twoHoursBefore = new Date()
twoHoursBefore.setHours(new Date().getHours() - 2)
const approveRequest = React.useCallback(async () => {
if (didDecrypt) {
const json = {
method: 'submitGuestList',
jsonrpc: '2.0',
id: uuidv4(),
params: {
_client: {
name: 'Recover',
},
dataAuthorizationToken: dataRequest.irisDataAuthorizationToken,
guestList: {
dataProvider: {
name: company.name,
address: {
street: company.street.split(',')[0],
houseNumber: company.street.split(',')[1],
zipCode: company.zip,
city: company.city,
},
},
startDate: dataRequest.from,
endDate: dataRequest.to,
additionalInformation: dataRequest.reason,
guests: tickets.map((ticket) => {
const result = {
lastName: ticket.guest.name,
phone: ticket.guest.phone,
address: {
street: ticket.guest.address,
},
attendanceInformation: {
attendFrom: ticket.enteredAt,
attendTo: ticket.leftAt,
additionalInformation: ticket.areaName,
},
}
return result
}),
},
},
}
return await ky
.post(`https://${dataRequest.proxyEndpoint}:32325`, { json })
.json()
.then((res) => {
if (res['result'] == 'OK') {
postAcceptDataRequest(dataRequestId).then(() => {
queryCache.find(['dataRequests', companyId, dataRequestId])
queryCache.find(['unacceptedDataRequests'])
openModal('success', {
returnUrl: `/business/company/${companyId}`,
text: t('approveRequestModalText'),
title: t('approveRequestModalTitle'),
})
})
} else {
console.log(res)
}
})
}
}, [
t,
didDecrypt,
tickets,
company,
dataRequest,
dataRequestId,
companyId,
openModal,
])
return (
<OwnerApp title={title}>
<Loading show={loading} />
{modals}
<BackLink
href="/business/company/[companyId]"
as={`/business/company/${companyId}`}
>
{company?.name}
</BackLink>
<Box height={2} />
{status !== 'success' && <Text variant="shy">{t('loading')}</Text>}
{dataRequest &&
!dataRequest.acceptedAt &&
pendingCount === 0 &&
errorCount === 0 && (
<>
<Callout variant="danger">
<Text>{t('acceptedAt1')}</Text>
<Box height={4} />
<Text as="h2">{t('acceptedAt2')}</Text>
<Text>{dataRequest.irisClientName}</Text>
<Box height={4} />
{dataRequest.reason && (
<>
<Text as="h2">{t('acceptedAt3')}</Text>
<Text>{dataRequest.reason}</Text>
<Box height={4} />
</>
)}
<Button onClick={approveRequest}>{t('acceptedAt3')}</Button>
</Callout>
<Box height={4} />
</>
)}
{dataRequest?.tickets && !owner.privateKey && (
<Box mb={4}>
<Text>{t('enterKeyMessage')}</Text>
<Box height={4} />
<Button onClick={handleEnterKey}>{t('enterKeyButtonText')}</Button>
</Box>
)}
{didDecrypt && (
<Box>
<Text variant="shy">
{successCount} {t('checkinsDecoded')}
</Text>
{errorCount > 0 && (
<Text variant="shy">
{errorCount} {t('checkinsErrorCountText')}
</Text>
)}
<Box height={4} />
{successCount === 0 && errorCount > 0 && (
<>
<Callout variant="danger">
<Text>{t('checkinsErrorCountMessage')}</Text>
</Callout>
<Box height={4} />
<Button type="button" onClick={handleEnterKey}>
{t('enterNewKeyButtonText')}
</Button>
</>
)}
<FlexibleRow>
<FlexibleRowStart>
<Box height={4} />
<Button onClick={handleDownload}>{t('downloadAsExcel')}</Button>
</FlexibleRowStart>
<FlexibleRowEnd>
<InfoRowItem>
<FilledCircle variant="cyan" />
{t('contactsFromLastHours')}
</InfoRowItem>
<InfoRowItem>
<FilledCircle variant="lilac" />
{t('olderContactRequests')}
</InfoRowItem>
</FlexibleRowEnd>
</FlexibleRow>
</Box>
)}
<Box mx={-4} p={4} css={{ overflow: 'scroll' }}>
<Table css={{ maxWidth: '100%' }}>
<thead>
<tr>
<th>{headerFrom}</th>
<th>{headerUntil}</th>
<th>{headerAreaName}</th>
<th>{headerName}</th>
<th>{headerAddress}</th>
<th>{headerPhone}</th>
{company?.needToShowCoronaTest && (
<th>{headerProvidedHealthDocument}</th>
)}
{isCareEnv && <th>{headerResidents}</th>}
</tr>
</thead>
<tbody>
{sortTickets(tickets).map((ticket) => (
<tr
key={ticket.id}
css={css({
bg:
ticket.leftAt >= twoHoursBefore ? 'cyan.100' : 'lilac.100',
})}
>
<td>{formatDate(ticket.enteredAt, 'DD.MM.YYYY HH:mm')}</td>
<td>
{ticket.leftAt
? formatDate(ticket.leftAt, 'DD.MM.YYYY HH:mm')
: '–'}
</td>
<td>{ticket.areaName}</td>
{ticket.decryptionStatus === 'pending' && (
<td colSpan={3}>{t('stillEncrypted')}</td>
)}
{ticket.decryptionStatus === 'error' && (
<td colSpan={3}>{t('notDecodable')}</td>
)}
{ticket.decryptionStatus === 'success' && (
<>
<td>{ticket.guest.name}</td>
<td>{ticket.guest.address}</td>
<td>{ticket.guest.phone}</td>
{company?.needToShowCoronaTest > 0 && (
<td>
{providedHealthDocumentToString(
ticket.guest.providedHealthDocument,
downloadFileLocales
)}
</td>
)}
{isCareEnv && <td>{ticket.guest.resident}</td>}
</>
)}
</tr>
))}
</tbody>
</Table>
</Box>
</OwnerApp>
)
}
Example #12
Source File: chartFactory.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
ChartBaseFactory = {
create: ({ moduleName, chartName, dataHandler }: ICreateChartProps) => {
const getQuery = (props: IChartProps) => {
const { query = {}, timeSpan, terminusKey, chosenApp, fetchApi, params } = props;
const commonState = {
...timeSpan,
chosenApp,
terminusKey,
fetchApi,
...params,
}; // 提供被查询的参数
const { constQuery = {}, dependentKey, ...rest } = query;
const reQuery = {};
if (dependentKey) {
// 接口中所需参数名命名不一致,如{tk:'terminusKey'}
Object.keys(dependentKey).forEach((key) => {
const curKey = dependentKey[key];
if (has(commonState, curKey)) {
const val = get(commonState, curKey);
val !== undefined && val !== '' && (reQuery[key] = commonState[curKey]);
} else {
// eslint-disable-next-line no-console
console.error(`there has no key:${curKey} in chartFactory, or the value of the key is undefined.`);
}
});
}
return {
query: { fetchApi, ...reQuery, ...rest, ...constQuery },
moduleName,
chartName,
dataHandler,
}; // 有静态查询参数,覆盖前面的参数,如固定的时间
};
const ChartBase = (props: IChartProps) => {
const { titleText, viewType, viewRender, viewProps, groupId, shouldLoad = true, ...otherProps } = props;
const { query = emptyObj, fetchApi } = otherProps;
const { loadChart } = monitorChartStore.effects;
const { clearChartData } = monitorChartStore.reducers;
const chart = monitorChartStore.useStore((s) => s);
const data = get(chart, `${moduleName}.${chartName}`, {});
const [timeSpan, chosenSortItem, chosenApp = {}] = monitorCommonStore.useStore((s) => [
s.globalTimeSelectSpan.range,
s.chosenSortItem,
s.chosenApp,
]);
const terminusKey = routeInfoStore.useStore((s) => s.params.terminusKey);
const [curQuery, setCurQuery] = React.useState(
getQuery({
...props,
timeSpan,
chosenSortItem,
chosenApp,
terminusKey,
}) as any,
);
let id = chartId;
useEffectOnce(() => {
id = chartId;
chartId += 1;
if (shouldLoad) {
const q = getQuery({
...props,
timeSpan,
chosenSortItem,
chosenApp,
terminusKey,
});
setCurQuery(q);
loadList.push({ id, loadChart, dataHandler, query: q });
}
// only start load after the last chart mounted
loadStart = setTimeout(() => {
if (loadStart) clearTimeout(loadStart);
loadStart = setTimeout(() => lazyLoad(), 0);
}, 0);
return () => {
if (timerMap[id]) {
clearTimeout(timerMap[id]);
}
clearChartData({ chartName, moduleName });
};
});
React.useEffect(() => {
if (!shouldLoad) {
setCurQuery({});
}
}, [shouldLoad]);
React.useEffect(() => {
const preQuery = curQuery;
const nextQuery = getQuery({
...props,
timeSpan,
chosenSortItem,
chosenApp,
terminusKey,
});
if (shouldLoad && !isEqualQuery(preQuery, nextQuery)) {
setCurQuery(nextQuery);
loadChart(nextQuery);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [shouldLoad, query, fetchApi, curQuery, timeSpan, chosenSortItem, chosenApp, terminusKey]);
let Chart: any;
switch (viewType) {
case 'pie':
Chart = PieChart;
break;
case 'map':
Chart = MapChart;
break;
case 'hollow-pie':
Chart = HollowPieChart;
break;
default:
Chart = viewRender || MonitorChartNew;
}
const title = titleText === false ? '' : data.title || titleText;
return (
<ChartContainer title={title}>
{
<Chart
{...otherProps}
_moduleName={moduleName} // TODO: use a inner named prop to prevent effect, only used in slow-tract-panel, need to refactor
timeSpan={timeSpan}
data={shouldLoad ? data : { loading: false }}
reload={() => {
loadChart({
...curQuery,
dataHandler,
});
}}
groupId={groupId}
{...viewProps}
/>
}
</ChartContainer>
);
};
return ChartBase;
},
}