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