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 #[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}