Skip to content

Commit

Permalink
Merge pull request #531 from logion-network/feature/fix-acknowledge
Browse files Browse the repository at this point in the history
Acknowledgment of items
  • Loading branch information
gdethier authored Nov 21, 2023
2 parents 019f9cc + 147a0c2 commit 117b9a3
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 58 deletions.
22 changes: 22 additions & 0 deletions src/ExtrinsicSubmissionStateView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useLogionChain } from './logion-chain/LogionChainContext';
import ExtrinsicSubmissionResult from './ExtrinsicSubmissionResult';

export interface Props {
successMessage?: string;
slim?: boolean;
}

export default function ExtrinsicSubmissionStateView(props: Props) {
const { extrinsicSubmissionState } = useLogionChain();

if(extrinsicSubmissionState.submitted) {
return (<ExtrinsicSubmissionResult
error={ extrinsicSubmissionState.error }
result={ extrinsicSubmissionState.result }
successMessage={ props.successMessage }
slim={ props.slim }
/>);
} else {
return null;
}
}
98 changes: 41 additions & 57 deletions src/loc/AcknowledgeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,22 @@ import Button, { Action } from "src/common/Button";
import Icon from "src/common/Icon";
import { LocItem, MetadataData, FileData, LinkData } from "./LocItem";
import Dialog from "src/common/Dialog";
import ClientExtrinsicSubmitter, { Call, CallCallback } from "src/ClientExtrinsicSubmitter";
import EstimatedFees from "./fees/EstimatedFees";
import { useLocContext } from "./LocContext";
import Alert from "src/common/Alert";
import { useLogionChain } from "src/logion-chain";
import { useLogionChain, CallCallback } from "src/logion-chain";
import "./AcknowledgeButton.css";
import ExtrinsicSubmissionStateView from "src/ExtrinsicSubmissionStateView";

export interface Props {
locItem: LocItem;
}

enum State {
INIT,
PREVIEW,
ACKNOWLEDGING,
ACKNOWLEDGED,
ERROR,
}

export default function AcknowledgeButton(props: Props) {
const [ state, setState ] = useState(State.INIT);
const [ showDialog, setShowDialog ] = useState(false);
const [ fees, setFees ] = useState<Fees | undefined | null>();
const [ call, setCall ] = useState<Call>();
const { mutateLocState, locState } = useLocContext();
const { signer } = useLogionChain();
const { signer, submitCall, clearSubmissionState, extrinsicSubmissionState } = useLogionChain();

useEffect(() => {
if(fees === undefined) {
Expand Down Expand Up @@ -59,65 +50,61 @@ export default function AcknowledgeButton(props: Props) {
}, [ fees, props.locItem, locState ]);

const preview = useCallback(() => {
setState(State.PREVIEW);
setShowDialog(true);
}, []);

const close = useCallback(() => {
setState(State.INIT);
}, []);
setShowDialog(false);
clearSubmissionState();
}, [ clearSubmissionState ]);

const acknowledge = useCallback(async () => {
setState(State.ACKNOWLEDGING);
const call = async (callback: CallCallback) =>
const call = useMemo(() => {
return async (callback: CallCallback) =>
mutateLocState(async current => {
if(signer && current instanceof OpenLoc) {
if(props.locItem.type === "Document") {
return current.legalOfficer.acknowledgeFile({
hash: props.locItem.as<FileData>().hash,
signer,
callback,
});
} else if(props.locItem.type === "Data") {
return current.legalOfficer.acknowledgeMetadata({
nameHash: props.locItem.as<MetadataData>().name.hash,
signer,
callback,
});
} else if(props.locItem.type === "Linked LOC") {
return current.legalOfficer.acknowledgeLink({
target: props.locItem.as<LinkData>().linkedLoc.id,
signer,
callback,
});
} else {
throw new Error("Unexpected type");
}
if(signer && current instanceof OpenLoc) {
if(props.locItem.type === "Document") {
return current.legalOfficer.acknowledgeFile({
hash: props.locItem.as<FileData>().hash,
signer,
callback,
});
} else if(props.locItem.type === "Data") {
return current.legalOfficer.acknowledgeMetadata({
nameHash: props.locItem.as<MetadataData>().name.hash,
signer,
callback,
});
} else if(props.locItem.type === "Linked LOC") {
return current.legalOfficer.acknowledgeLink({
target: props.locItem.as<LinkData>().linkedLoc.id,
signer,
callback,
});
} else {
return current;
throw new Error("Unexpected type");
}
});
setCall(() => call);
}, [ mutateLocState, signer, props.locItem ]);
} else {
return current;
}
});
}, [ mutateLocState, props.locItem, signer ]);

const actions = useMemo(() => {
const actions: Action[] = [];
if(state === State.PREVIEW || state === State.ERROR) {
if(!extrinsicSubmissionState.submitted) {
actions.push({
id: "cancel",
buttonText: "Cancel",
buttonVariant: "secondary",
callback: close,
});
}
if(state === State.PREVIEW) {
actions.push({
id: "proceed",
buttonText: "Proceed",
buttonVariant: "polkadot",
callback: acknowledge,
callback: () => submitCall(call),
});
}
if(state === State.ACKNOWLEDGED) {
} else if(extrinsicSubmissionState.callEnded) {
actions.push({
id: "close",
buttonText: "Close",
Expand All @@ -126,7 +113,7 @@ export default function AcknowledgeButton(props: Props) {
});
}
return actions;
}, [ state, close, acknowledge ]);
}, [ close, submitCall, extrinsicSubmissionState, call ]);

return (
<>
Expand All @@ -137,7 +124,7 @@ export default function AcknowledgeButton(props: Props) {
<Icon icon={{ id: "shield" }} /> Acknowledge
</Button>
<Dialog
show={ state !== State.INIT }
show={ showDialog }
actions={ actions }
size="lg"
className="AcknowledgeButton"
Expand All @@ -152,11 +139,8 @@ export default function AcknowledgeButton(props: Props) {
centered={ true }
/>
<div className="submitter-container">
<ClientExtrinsicSubmitter
call={ call }
<ExtrinsicSubmissionStateView
successMessage="Successfully acknowledged"
onSuccess={ () => setState(State.ACKNOWLEDGED) }
onError={ () => setState(State.ERROR) }
/>
</div>
</Dialog>
Expand Down
30 changes: 29 additions & 1 deletion src/logion-chain/LogionChainContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export interface LogionChainContextType {
submitCall: (call: Call) => Promise<void>;
submitSignAndSubmit: (signAndSubmit: SignAndSubmit) => void;
resetSubmissionState: () => void;
clearSubmissionState: () => void;
}

export interface FullLogionChainContextType extends LogionChainContextType {
Expand Down Expand Up @@ -201,6 +202,7 @@ const initState = (): FullLogionChainContextType => ({
submitCall: () => Promise.reject(),
submitSignAndSubmit: () => {},
resetSubmissionState: () => {},
clearSubmissionState: () => {},
});

type ActionType = 'SET_SELECT_ADDRESS'
Expand Down Expand Up @@ -230,6 +232,8 @@ type ActionType = 'SET_SELECT_ADDRESS'
| 'SET_SUBMIT_SIGN_AND_SUBMIT'
| 'SET_RESET_SUBMISSION_STATE'
| 'RESET_SUBMISSION_STATE'
| 'SET_CLEAR_SUBMISSION_STATE'
| 'CLEAR_SUBMISSION_STATE'
;

interface Action {
Expand Down Expand Up @@ -258,6 +262,7 @@ interface Action {
extrinsicSubmissionError?: unknown;
submitSignAndSubmit?: (signAndSubmit: SignAndSubmit) => void;
resetSubmissionState?: () => void;
clearSubmissionState?: () => void;
}

function buildAxiosFactory(authenticatedClient?: LogionClient): AxiosFactory {
Expand Down Expand Up @@ -455,7 +460,7 @@ const reducer: Reducer<FullLogionChainContextType, Action> = (state: FullLogionC
case 'SET_SUBMISSION_ENDED':
return {
...state,
extrinsicSubmissionState: state.extrinsicSubmissionState.end(action.error || null),
extrinsicSubmissionState: state.extrinsicSubmissionState.end(action.extrinsicSubmissionError || null),
};
case 'SET_SUBMIT_SIGN_AND_SUBMIT':
return {
Expand All @@ -472,6 +477,16 @@ const reducer: Reducer<FullLogionChainContextType, Action> = (state: FullLogionC
...state,
extrinsicSubmissionState: state.extrinsicSubmissionState.resetAndKeepResult(),
};
case 'SET_CLEAR_SUBMISSION_STATE':
return {
...state,
clearSubmissionState: action.clearSubmissionState!,
};
case 'CLEAR_SUBMISSION_STATE':
return {
...state,
extrinsicSubmissionState: new ExtrinsicSubmissionState(),
};
default:
/* istanbul ignore next */
throw new Error(`Unknown type: ${action.type}`);
Expand Down Expand Up @@ -836,6 +851,19 @@ const LogionChainContextProvider = (props: LogionChainContextProviderProps): JSX
}
}, [ state.resetSubmissionState, resetSubmissionState ]);

const clearSubmissionState = useCallback(() => {
dispatch({ type: 'CLEAR_SUBMISSION_STATE' });
}, [ ]);

useEffect(() => {
if(state.clearSubmissionState !== clearSubmissionState) {
dispatch({
type: 'SET_CLEAR_SUBMISSION_STATE',
clearSubmissionState,
});
}
}, [ state.clearSubmissionState, clearSubmissionState ]);

return <LogionChainContext.Provider value={state}>
{props.children}
</LogionChainContext.Provider>;
Expand Down
2 changes: 2 additions & 0 deletions src/logion-chain/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
useLogionChain,
LogionChainContextProvider,
AxiosFactory,
CallCallback,
} from './LogionChainContext';

export {
Expand All @@ -10,4 +11,5 @@ export {
};
export type {
AxiosFactory,
CallCallback,
};

0 comments on commit 117b9a3

Please sign in to comment.