github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/cloud/dashboard/src/components/image_list.rs (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 use crate::routes::{router::Anchor, router::AppRoute}; 16 use crate::services::requests::{Image, Images, RegistryCatalog}; 17 use yew::services::ConsoleService; 18 use serde::Deserialize; 19 use yew::{ 20 format::{Json, Nothing}, 21 html, 22 services::fetch::{FetchService, FetchTask, Request, Response}, 23 Component, ComponentLink, Html, ShouldRender, 24 }; 25 26 #[derive(Debug)] 27 pub enum Msg { 28 GetRegistryCatelog(Result<RegistryCatalog, anyhow::Error>), 29 } 30 31 enum Class { 32 Provider, 33 Categories, 34 OperatingSystems, 35 Architectrues, 36 } 37 38 enum Label { 39 ThirdPart(Class, String), 40 Official(Class, String), 41 42 Analytics(Class, String), 43 ApplicationRuntime(Class, String), 44 BaseImages(Class, String), 45 Databases(Class, String), 46 DevOps(Class, String), 47 Messaging(Class, String), 48 Monitoring(Class, String), 49 OperatingSystem(Class, String), 50 Storage(Class, String), 51 Networking(Class, String), 52 53 Linux(Class, String), 54 Windows(Class, String), 55 56 ARM64(Class, String), 57 AMD64(Class, String), 58 } 59 60 impl Component for Images { 61 type Message = Msg; 62 type Properties = (); 63 64 fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self { 65 ConsoleService::info("create app"); 66 Self { 67 repos: None, 68 link, 69 error: None, 70 task: None, 71 } 72 } 73 74 fn update(&mut self, msg: Self::Message) -> ShouldRender { 75 use Msg::*; 76 match msg { 77 GetRegistryCatelog(response) => match response { 78 Ok(repos) => { 79 ConsoleService::info(&format!("info {:?}", repos)); 80 self.repos = Some(repos.repositories); 81 } 82 Err(error) => { 83 ConsoleService::info(&format!("info {:?}", error.to_string())); 84 }, 85 }, 86 } 87 true 88 } 89 90 fn rendered(&mut self, first_render: bool) { 91 if first_render { 92 ConsoleService::info("view app"); 93 let request = Request::get("http://localhost:8001/v2/_catalog") 94 .body(Nothing) 95 .expect("could not build request."); 96 let callback = self.link.callback( 97 |response: Response<Json<Result<RegistryCatalog, anyhow::Error>>>| { 98 let Json(data) = response.into_body(); 99 Msg::GetRegistryCatelog(data) 100 }, 101 ); 102 let task = FetchService::fetch(request, callback).expect("failed to start request"); 103 self.task = Some(task); 104 } 105 } 106 107 fn change(&mut self, props: Self::Properties) -> ShouldRender { 108 true 109 } 110 111 fn view(&self) -> Html { 112 html! { 113 <div> 114 <div class="columns is-multiline"> 115 <div class="container column is-1"> 116 { self.filter() } 117 </div> 118 <div class="container column is-10"> 119 { self.image_list() } 120 </div> 121 </div> 122 </div> 123 } 124 } 125 126 fn destroy(&mut self) {} 127 } 128 129 impl Images { 130 fn filter(&self) -> Html { 131 html! { 132 <aside class="menu"> 133 <p class="menu-label"> 134 { "Provider" } 135 </p> 136 <ul class="menu-list"> 137 <li><a>{ "Official" }</a></li> 138 <li><a>{ "ThirdPart" }</a></li> 139 </ul> 140 <p class="menu-label"> 141 { "Categories" } 142 </p> 143 <ul class="menu-list"> 144 <li><a>{ "BaseImage" }</a></li> 145 <li><a>{ "DataBases" }</a></li> 146 <li><a>{ "Messaging" }</a></li> 147 <li><a>{ "Monitoring" }</a></li> 148 </ul> 149 <p class="menu-label"> 150 { "Architecutures" } 151 </p> 152 <ul class="menu-list"> 153 <li><a>{ "ARM64" }</a></li> 154 <li><a>{ "AMD64" }</a></li> 155 </ul> 156 </aside> 157 } 158 } 159 fn image_list(&self) -> Html { 160 match &self.repos { 161 Some(images) => { 162 html! { 163 <div class="columns is-multiline"> 164 { 165 for images.iter().map(|image|{ 166 self.image_info(image) 167 }) 168 } 169 </div> 170 } 171 } 172 None => { 173 html! { 174 <p> {"image not found"} </p> 175 } 176 } 177 } 178 } 179 180 fn image_info(&self, image: &String) -> Html { 181 html! { 182 <div class="column is-6"> 183 <div class="card"> 184 <Anchor route=AppRoute::ImageDetail(image.to_string())> 185 <header class="card-header"> 186 <p class="card-header-title"> 187 { image.to_string() } 188 </p> 189 <button class="card-header-icon" aria-label="more options"> 190 <span class="icon"> 191 <i class="fal fa-expand" aria-hidden="true"></i> 192 </span> 193 </button> 194 </header> 195 </Anchor> 196 <div class="card-content"> 197 <div class="content"> 198 { "describe" } 199 <br /> 200 <time datetime="2016-1-1">{ "11:09 PM - 1 Jan 2016" }</time> 201 </div> 202 </div> 203 </div> 204 </div> 205 } 206 } 207 }