Skip to main content

edc_web_components/components/
dataset_card.rs

1use crate::models::DataspaceDataset;
2use patternfly_yew::prelude::*;
3use stylist::yew::styled_component;
4use yew::prelude::*;
5
6#[derive(Clone, PartialEq, Properties)]
7pub struct DatasetCardProps {
8  pub dataset: DataspaceDataset,
9  #[prop_or_default]
10  pub on_offer_click: Option<Callback<()>>,
11  #[prop_or(AttrValue::Static("Select"))]
12  pub button_label: AttrValue,
13}
14
15#[styled_component]
16pub fn DatasetCard(props: &DatasetCardProps) -> Html {
17  let card_class = css!(
18    width: 250px;
19  );
20
21  let thumbnails_class = css!(
22    height: 180px;
23    object-fit: cover;
24  );
25
26  let provider_logo_class = css!(
27    width: 50px;
28    height: 50px;
29    object-fit: contain;
30  );
31
32  let version_class = css!(
33    position: absolute;
34    top: 5px;
35    right: 5px;
36  );
37
38  let keyword_class = css!(
39    .pf-v6-l-split {
40      overflow: hidden;
41    }
42  );
43
44  let description_class = css!(
45    display: block;
46    display: -webkit-box;
47    -webkit-line-clamp: 5;
48    -webkit-box-orient: vertical;
49    text-overflow: ellipsis;
50    overflow: hidden;
51  );
52
53  let offer_button_class = css!(
54    text-align: right;
55  );
56
57  let offer_button = if let Some(offer) = props.on_offer_click.clone() {
58    html!(
59      <Button
60        variant={ButtonVariant::Primary}
61        icon={Icon::AngleRight}
62        onclick={offer.reform(|_| ())}
63      >
64        { props.button_label.clone() }
65      </Button>
66    )
67  } else {
68    html!()
69  };
70
71  let title = props.dataset.title.to_string();
72
73  let version = props
74    .dataset
75    .version
76    .clone()
77    .map(|version| version.to_string())
78    .unwrap_or_default();
79
80  let comment = props.dataset.comment.clone().unwrap_or_default();
81
82  let thumbnail = props
83    .dataset
84    .thumbnail
85    .clone()
86    .and_then(|thumbnail| thumbnail.resource)
87    .map(|thumbnail| html! { <img src={thumbnail} class={thumbnails_class.clone()} /> });
88
89  let provider_logo = props
90    .dataset
91    .creator
92    .clone()
93    .and_then(|creator| creator.thumbnail)
94    .and_then(|thumbnail| thumbnail.resource)
95    .map(|thumbnail| html! { <img src={thumbnail} class={provider_logo_class.clone()} /> });
96
97  let keywords = props.dataset.keywords.iter().map(|keyword| {
98    html_nested! {
99      <SplitItem>
100        <Label label={keyword.clone()} />
101      </SplitItem>
102    }
103  });
104
105  html!(
106    <Card full_height=true class={card_class.clone()}>
107      { thumbnail }
108      <div class={version_class.clone()}>
109        <Badge read=true>{ "v" }{ version }</Badge>
110      </div>
111      <CardTitle>
112        <div>{ provider_logo }</div>
113        <Truncate content={title} />
114      </CardTitle>
115      <CardBody>
116        <Stack gutter=true>
117          <StackItem fill=true>
118            <div class={description_class.clone()}>{ comment }</div>
119          </StackItem>
120          <StackItem>
121            <div class={offer_button_class.clone()}>{ offer_button.clone() }</div>
122          </StackItem>
123        </Stack>
124      </CardBody>
125      <CardFooter>
126        <slot class={keyword_class.clone()}>
127          <Split gutter=true>{ for keywords }</Split>
128        </slot>
129      </CardFooter>
130    </Card>
131  )
132}