edc_web_components/components/
dataset_card.rs1use 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}