edc_web_components/components/
contract_negotiation_status.rs1use crate::contexts::use_edc_connector_context;
2use edc_connector_client::types::contract_negotiation::{
3 ContractNegotiation, ContractNegotiationState,
4};
5use patternfly_yew::prelude::*;
6use std::time::Duration;
7use yew::platform::spawn_local;
8use yew::platform::time::sleep;
9use yew::prelude::*;
10
11const HAPPY_PATH_STATES: [(&str, ContractNegotiationState); 7] = [
12 ("Initial", ContractNegotiationState::Initial),
13 ("Requested", ContractNegotiationState::Requested),
14 ("Offered", ContractNegotiationState::Offered),
15 ("Accepted", ContractNegotiationState::Accepted),
16 ("Agreed", ContractNegotiationState::Agreed),
17 ("Verified", ContractNegotiationState::Verified),
18 ("Finalized", ContractNegotiationState::Finalized),
19];
20
21#[derive(Clone, Debug, PartialEq, Properties)]
22pub struct ContractNegotiationStatusProps {
23 pub contract_negotiation_id: String,
24 pub on_finalized: Callback<()>,
25}
26
27#[component]
28pub fn ContractNegotiationStatus(props: &ContractNegotiationStatusProps) -> Html {
29 let edc_connector_client = use_edc_connector_context();
30
31 let contract_negotiation_state = use_state(|| None);
32 let contract_negotiation_error = use_state(|| None);
33
34 use_effect_with(
35 (
36 props.contract_negotiation_id.clone(),
37 edc_connector_client.clone(),
38 contract_negotiation_state.setter(),
39 contract_negotiation_error.setter(),
40 props.on_finalized.clone(),
41 ),
42 |(
43 contract_negotiation_id,
44 edc_connector_client,
45 contract_negotiation_state_setter,
46 contract_negotiation_error_setter,
47 on_finalized,
48 )| {
49 let contract_negotiation_id = contract_negotiation_id.clone();
50 let edc_connector_client = edc_connector_client.clone();
51 let contract_negotiation_state_setter = contract_negotiation_state_setter.clone();
52 let contract_negotiation_error_setter = contract_negotiation_error_setter.clone();
53 let on_finalized = on_finalized.clone();
54
55 spawn_local(async move {
56 loop {
57 let contract_negotiation = if let Some(client) = edc_connector_client.get_client() {
58 client
59 .contract_negotiations(edc_connector_client::EdcConnectorApiVersion::V4)
60 .get(&contract_negotiation_id)
61 .await
62 .ok()
63 } else {
64 None
65 };
66
67 let state = contract_negotiation
68 .as_ref()
69 .map(|contract_negotiation| contract_negotiation.state().clone());
70
71 let error_message = contract_negotiation
72 .as_ref()
73 .and_then(|contract_negotiation| {
74 contract_negotiation
75 .error_detail()
76 .map(|error_detail| error_detail.to_string())
77 });
78
79 contract_negotiation_error_setter.set(error_message);
80
81 contract_negotiation_state_setter.set(contract_negotiation);
82
83 if state == Some(ContractNegotiationState::Finalized)
84 || state == Some(ContractNegotiationState::Terminated)
85 {
86 on_finalized.emit(());
87 break;
88 }
89
90 sleep(Duration::from_secs(1)).await;
91 }
92 });
93 },
94 );
95
96 match (
97 (*contract_negotiation_error).clone(),
98 (*contract_negotiation_state).clone(),
99 ) {
100 (Some(error_message), _) => html!(
101 <Alert title="Negotiation failed" r#type={AlertType::Danger}>
102 <div>{ error_message }</div>
103 </Alert>
104 ),
105 (None, Some(contract_negotiation)) => {
106 let contract_negotiation: ContractNegotiation = contract_negotiation;
107
108 let current_state_index = HAPPY_PATH_STATES
109 .iter()
110 .position(|(_, state)| state == contract_negotiation.state())
111 .unwrap_or_default();
112
113 let steps = HAPPY_PATH_STATES
114 .iter()
115 .enumerate()
116 .map(|(index, (state_label, _))| {
117 let status = if index < current_state_index {
118 ProgressStepperStepStatus::Success
119 } else if index == current_state_index {
120 if index == HAPPY_PATH_STATES.len() - 1 {
121 ProgressStepperStepStatus::Success
122 } else {
123 ProgressStepperStepStatus::Default
124 }
125 } else {
126 ProgressStepperStepStatus::Pending
127 };
128
129 html_nested!(
130 <ProgressStepperStep {status}>
131 <div>{ state_label.to_string() }</div>
132 </ProgressStepperStep>
133 )
134 });
135
136 html!(<ProgressStepper>{ for steps }</ProgressStepper>)
137 }
138 _ => html!(),
139 }
140}