diff --git a/ui/src/pages/QuickSetup/AccountSelectionModal.tsx b/ui/src/pages/QuickSetup/AccountSelection.tsx
similarity index 65%
rename from ui/src/pages/QuickSetup/AccountSelectionModal.tsx
rename to ui/src/pages/QuickSetup/AccountSelection.tsx
index eb47e468..606c1bb2 100644
--- a/ui/src/pages/QuickSetup/AccountSelectionModal.tsx
+++ b/ui/src/pages/QuickSetup/AccountSelection.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from 'react';
+import React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { damlSetValues, makeDamlSet, createDropdownProp } from '../common';
import { useStreamQueries } from '../../Main';
@@ -7,7 +7,7 @@ import {
RequestOpenAccount,
RequestOpenAllocationAccount,
} from '@daml.js/da-marketplace/lib/Marketplace/Custody/Service';
-import { DropdownItemProps, Form, Modal, Button, DropdownProps } from 'semantic-ui-react';
+import { DropdownItemProps, Form, DropdownProps } from 'semantic-ui-react';
import { useLedger } from '@daml/react';
import { Service as CustodyService } from '@daml.js/da-marketplace/lib/Marketplace/Custody/Service/';
import { usePartyName } from '../../config';
@@ -15,7 +15,7 @@ import {
OpenAccountRequest,
OpenAllocationAccountRequest,
} from '@daml.js/da-marketplace/lib/Marketplace/Custody/Model';
-import { IPartyAccounts } from './RequestServicesPage';
+import { IPartyAccounts, AccountsForServices } from './RequestServicesPage';
import { Party } from '@daml/types';
import _ from 'lodash';
import { Account } from '@daml.js/da-marketplace/lib/DA/Finance/Types';
@@ -31,33 +31,24 @@ type AccountInfo = {
accountLabel: string;
};
export type AccountInfos = { [k: string]: AccountInfo };
-export type SetFunction = (accts: { [k: string]: Account | undefined }) => void;
-
-type NameMap = { [k: string]: string | undefined };
type Props = {
party: Party;
serviceProvider?: Party;
- open: boolean;
- setOpen: (bool: boolean) => void;
accountsForParty?: IPartyAccounts;
accountInfos: AccountInfos;
- onCancel: () => void;
- onFinish: SetFunction;
+ accountsForServices: AccountsForServices;
+ onChangeAccount: (k: string, acct: Account | undefined) => void;
};
-const AccountSelectionModal: React.FC = ({
+const AccountSelection: React.FC = ({
party,
serviceProvider,
- open,
- setOpen,
+ accountsForServices,
accountsForParty,
accountInfos,
- onFinish,
- onCancel,
+ onChangeAccount,
}) => {
- const { getName } = usePartyName(party);
-
const hasRegularAccount = _.values(accountInfos).reduce(
(acc, info) => acc || info.accountType === AccountType.REGULAR,
false
@@ -67,21 +58,6 @@ const AccountSelectionModal: React.FC = ({
false
);
- const emptyNamesState = _.mapValues(accountInfos, () => {
- return undefined;
- });
- const [accountNamesState, setAccountNamesState] = useState(emptyNamesState);
-
- useEffect(() => {
- setAccountNamesState(prev =>
- _.mapValues(accountInfos, (_, key) => {
- return prev[key] || undefined;
- })
- );
- }, [accountInfos]);
-
- const disabled = _.values(accountNamesState).reduce((acc, name) => acc || !name, false);
-
const allocationAccountRules = accountsForParty?.allocAccounts || [];
const allocationAccounts = allocationAccountRules
.filter(c => c.payload.nominee === serviceProvider)
@@ -111,64 +87,31 @@ const AccountSelectionModal: React.FC = ({
const accountNeeded = hasRegularAccount && !accountNames.length && !openAccountRequests.length;
return (
- {
- const accts = _.mapValues(accountInfos, (accountInfo, k) => {
- const account =
- accountInfo.accountType === AccountType.REGULAR
- ? accounts.find(a => a.id.label === accountNamesState[k])
- : allocationAccounts.find(a => a.id.label === accountNamesState[k]);
- return account;
- });
- onFinish(accts);
- setAccountNamesState(emptyNamesState);
- setOpen(false);
- }}
- >
- {`Select Accounts for ${getName(party)} requesting from ${getName(
- serviceProvider || ''
- )}`}
-
- {!custodyServices.length && (allocationAccountNeeded || accountNeeded) ? (
- <>This party must have at least one Custody service>
- ) : (
- !!serviceProvider && (
-
- {_.toPairs(accountInfos).map(([k, accountInfo]) => (
-
- ))}
-
- )
- )}
-
-
-
-
-
-
+ <>
+ {!custodyServices.length && (allocationAccountNeeded || accountNeeded) ? (
+ <>This party must have at least one Custody service>
+ ) : (
+ !!serviceProvider && (
+
+ {_.toPairs(accountInfos).map(([k, accountInfo]) => (
+
+ ))}
+
+ )
+ )}
+ >
);
};
@@ -180,10 +123,10 @@ const ProviderOption = (props: {
openAccountRequests: CreateEvent[];
openAllocationAccountRequests: CreateEvent[];
custodyServices: CreateEvent[];
- accountNamesState: NameMap;
- setAccountNamesState: (setter: (prevState: NameMap) => NameMap) => void;
+ accountsForServices: { [k: string]: Account | undefined };
party: string;
serviceProvider: string;
+ onChangeAccount: (k: string, acct: Account | undefined) => void;
}) => {
const {
accountInfo,
@@ -194,24 +137,24 @@ const ProviderOption = (props: {
openAccountRequests,
openAllocationAccountRequests,
custodyServices,
- accountNamesState,
- setAccountNamesState,
+ accountsForServices,
+ onChangeAccount,
accountKey,
} = props;
const ledger = useLedger();
const { getName } = usePartyName(party);
+ const makeAccountName = (accountInfo: AccountInfo) =>
+ `${getName(party)}-${getName(serviceProvider)}-${accountInfo.accountLabel.replace(/\s+/g, '')}`;
+
const accountNames: DropdownItemProps[] = accounts.map(a => createDropdownProp(a.id.label));
- const allocationAccountNames: DropdownItemProps[] = allocationAccounts.map(a =>
- createDropdownProp(a.id.label)
- );
+ const allocationAccountNames: DropdownItemProps[] = allocationAccounts
+ .filter(acc => acc.id.label === makeAccountName(accountInfo))
+ .map(a => createDropdownProp(a.id.label));
const accountOptions =
accountInfo.accountType === AccountType.REGULAR ? accountNames : allocationAccountNames;
- const makeAccountName = (accountInfo: AccountInfo) =>
- `${getName(party)}-${getName(serviceProvider)}-${accountInfo.accountLabel.replace(/\s+/g, '')}`;
-
const requestAccount = async (provider: string, accountInfo: AccountInfo) => {
if (!serviceProvider) return;
const service = custodyServices.find(s => s.payload.provider === provider);
@@ -276,21 +219,22 @@ const ProviderOption = (props: {
if (prepend === accountRequestPrepend) {
requestAccount(rest[0], accountInfo);
} else {
- setAccountNamesState(prev => {
- let copy = { ...prev };
- copy[accountKey] = change.value as string;
- return copy;
- });
+ const account =
+ accountInfo.accountType === AccountType.REGULAR
+ ? accounts.find(a => a.id.label === (change.value as string))
+ : allocationAccounts.find(a => a.id.label === (change.value as string));
+ onChangeAccount(accountKey, account);
}
};
return (
<>
{accountInfo.accountLabel}
}
placeholder="Select..."
required
options={[...accountOptions, ...providerOptions]}
- value={accountNamesState[accountKey]}
+ value={accountsForServices[accountKey]?.id.label}
onChange={(_, change) => selectOrCreate(change)}
/>
{accountRequestExists(accountInfo) && Account request pending...
}
@@ -298,4 +242,4 @@ const ProviderOption = (props: {
);
};
-export default AccountSelectionModal;
+export default AccountSelection;
diff --git a/ui/src/pages/QuickSetup/RequestServicesPage.tsx b/ui/src/pages/QuickSetup/RequestServicesPage.tsx
index 812ef849..e169305d 100644
--- a/ui/src/pages/QuickSetup/RequestServicesPage.tsx
+++ b/ui/src/pages/QuickSetup/RequestServicesPage.tsx
@@ -38,15 +38,16 @@ import { Account } from '@daml.js/da-marketplace/lib/DA/Finance/Types';
import { CreateEvent } from '@daml/ledger';
import { AssetSettlementRule } from '@daml.js/da-marketplace/lib/DA/Finance/Asset/Settlement';
import { AllocationAccountRule } from '@daml.js/da-marketplace/lib/Marketplace/Rule/AllocationAccount';
-import AccountSelectionModal, { AccountType, AccountInfos } from './AccountSelectionModal';
+import AccountSelection, { AccountType, AccountInfos } from './AccountSelection';
-type AccountsForServices = {
+export type AccountsForServices = {
clearingAccount?: Account;
marginAccount?: Account;
tradingAccount?: Account;
tradingAllocAccount?: Account;
biddingAccount?: Account;
biddingAllocAccount?: Account;
+ issuanceAccount?: Account;
auctionAccount?: Account;
auctionAllocAccount?: Account;
receivableAccount?: Account;
@@ -170,77 +171,82 @@ const RequestForm = (props: {
const partyOptions = identities.map(p => {
return { text: p.payload.legalName, value: p.payload.customer };
});
- const [showAccountModal, setShowAccountModal] = useState(false);
- const [modalAccountInfos, setModalAccountInfos] = useState({});
- const [modalOnCancelFunction, setModalOnCancelFunction] = useState<() => void>(() => {
- return;
- });
- const selectAccounts = useCallback(
- (serviceType: ServiceKind) => {
- switch (serviceType) {
- case ServiceKind.CLEARING:
- setModalAccountInfos({
- clearingAccount: {
- accountType: AccountType.REGULAR,
- accountLabel: 'Clearing Account',
- },
- marginAccount: {
- accountType: AccountType.ALLOCATION,
- accountLabel: 'Margin Account',
- },
- });
- break;
- case ServiceKind.TRADING:
- setModalAccountInfos({
- tradingAccount: {
- accountType: AccountType.REGULAR,
- accountLabel: 'Exchange Trading Account',
- },
- tradingAllocAccount: {
- accountType: AccountType.ALLOCATION,
- accountLabel: 'Locked Account',
- },
- });
- break;
- case ServiceKind.BIDDING:
- setModalAccountInfos({
- biddingAccount: {
- accountType: AccountType.REGULAR,
- accountLabel: 'Bidding Account',
- },
- biddingAllocAccount: {
- accountType: AccountType.ALLOCATION,
- accountLabel: 'Bidding Locked Account',
- },
- });
- break;
- case ServiceKind.AUCTION:
- setModalAccountInfos({
- auctionAccount: {
- accountType: AccountType.REGULAR,
- accountLabel: 'Main Auction Account',
- },
- auctionAllocAccount: {
- accountType: AccountType.ALLOCATION,
- accountLabel: 'Locked Auction Account',
- },
- receivableAccount: {
- accountType: AccountType.REGULAR,
- accountLabel: 'Receivables Account',
- },
- });
- break;
- }
- setModalOnCancelFunction(
- () => () =>
- setRequestInfo({
- ...requestInfo,
- services: requestInfo?.services?.filter(s => s !== serviceType),
- })
- );
- setShowAccountModal(true);
+ const [accountSelectInfos, setAccountSelectInfos] = useState({});
+
+ const handleSetAccountInfos = useCallback(
+ (existing: ServiceKind[]) => {
+ const newAccountInfos =
+ requestInfo?.services?.reduce((acc, svc) => {
+ if (existing.includes(svc)) return acc;
+
+ switch (svc) {
+ case ServiceKind.CLEARING:
+ return {
+ ...acc,
+ clearingAccount: {
+ accountType: AccountType.REGULAR,
+ accountLabel: 'Clearing Account',
+ },
+ marginAccount: {
+ accountType: AccountType.ALLOCATION,
+ accountLabel: 'Margin Account',
+ },
+ };
+ case ServiceKind.ISSUANCE:
+ return {
+ ...acc,
+ issuanceAccount: {
+ accountType: AccountType.REGULAR,
+ accountLabel: 'Issuance Account',
+ },
+ };
+ case ServiceKind.TRADING:
+ return {
+ ...acc,
+ tradingAccount: {
+ accountType: AccountType.REGULAR,
+ accountLabel: 'Exchange Trading Account',
+ },
+ tradingAllocAccount: {
+ accountType: AccountType.ALLOCATION,
+ accountLabel: 'Exchange Locked Account',
+ },
+ };
+ case ServiceKind.BIDDING:
+ return {
+ ...acc,
+ biddingAccount: {
+ accountType: AccountType.REGULAR,
+ accountLabel: 'Bidding Account',
+ },
+ biddingAllocAccount: {
+ accountType: AccountType.ALLOCATION,
+ accountLabel: 'Bidding Locked Account',
+ },
+ };
+ case ServiceKind.AUCTION:
+ return {
+ ...acc,
+ auctionAccount: {
+ accountType: AccountType.REGULAR,
+ accountLabel: 'Main Auction Account',
+ },
+ auctionAllocAccount: {
+ accountType: AccountType.ALLOCATION,
+ accountLabel: 'Locked Auction Account',
+ },
+ receivableAccount: {
+ accountType: AccountType.REGULAR,
+ accountLabel: 'Receivables Account',
+ },
+ };
+ default:
+ return acc;
+ }
+ }, {}) || {};
+ setAccountSelectInfos(newAccountInfos);
},
- [requestInfo, setRequestInfo]
+ [requestInfo]
);
useEffect(() => {
@@ -254,31 +260,6 @@ const RequestForm = (props: {
return;
}
- const accounts = requestInfo?.accounts;
- if (requestServices.includes(ServiceKind.CLEARING)) {
- if (!accounts?.clearingAccount || !accounts?.marginAccount)
- selectAccounts(ServiceKind.CLEARING);
- }
-
- if (requestServices.includes(ServiceKind.TRADING)) {
- if (!accounts?.tradingAccount || !accounts?.tradingAllocAccount)
- selectAccounts(ServiceKind.TRADING);
- }
-
- if (requestServices.includes(ServiceKind.BIDDING)) {
- if (!accounts?.biddingAccount || !accounts?.biddingAllocAccount)
- selectAccounts(ServiceKind.BIDDING);
- }
-
- if (requestServices.includes(ServiceKind.AUCTION)) {
- if (
- !accounts?.auctionAccount ||
- !accounts?.auctionAllocAccount ||
- !accounts?.receivableAccount
- )
- selectAccounts(ServiceKind.AUCTION);
- }
-
const matchingContracts = services.filter(
s => s.contract.payload.provider === provider && s.contract.payload.customer === customer
);
@@ -292,12 +273,38 @@ const RequestForm = (props: {
} else {
setExistingServices([]);
}
- }, [requestInfo, services, setModalAccountInfos, setShowAccountModal, selectAccounts]);
+
+ handleSetAccountInfos(existingServices);
+ }, [requestInfo, services, setAccountSelectInfos, handleSetAccountInfos]);
if (identitiesLoading) {
return null;
}
+ const hasAccountsForServices = requestInfo?.services?.reduce((acc, svc) => {
+ if (existingServices.includes(svc)) return acc;
+ const accounts = requestInfo?.accounts;
+ switch (svc) {
+ case ServiceKind.CLEARING:
+ return acc && !!accounts?.clearingAccount && !!accounts?.marginAccount;
+ case ServiceKind.ISSUANCE:
+ return acc && !!accounts?.issuanceAccount;
+ case ServiceKind.TRADING:
+ return acc && !!accounts?.tradingAccount && !!accounts?.tradingAllocAccount;
+ case ServiceKind.BIDDING:
+ return acc && !!accounts?.biddingAccount && !!accounts?.biddingAllocAccount;
+ case ServiceKind.AUCTION:
+ return (
+ acc &&
+ !!accounts?.auctionAccount &&
+ !!accounts?.auctionAllocAccount &&
+ !!accounts?.receivableAccount
+ );
+ default:
+ return acc;
+ }
+ }, true);
+
return (
<>
- {existingServices.length > 0 && requestInfo?.provider && requestInfo?.customer && (
-
- {getName(requestInfo?.provider)} already provides{' '}
- {itemListAsText(existingServices || [])} services to {getName(requestInfo?.customer)}
-
- )}
-
-
+ {existingServices.length > 0 && requestInfo?.provider && requestInfo?.customer && (
+
+ {getName(requestInfo?.provider)} already provides{' '}
+ {itemListAsText(existingServices || [])} services to {getName(requestInfo?.customer)}
+
+ )}
+
{requestInfo && requestInfo.customer && token && (
-
Accounts:}
+ {
+ onChangeAccount={(k: string, acct: Account | undefined) => {
+ let acctsCopy: { [k: string]: Account | undefined } =
+ { ...requestInfo?.accounts } || {};
+ acctsCopy[k] = acct;
setRequestInfo({
...requestInfo,
- accounts: { ...requestInfo?.accounts, ...accts },
+ accounts: acctsCopy,
});
}}
/>
)}
+
+
+
>
);