|
15 | 15 | */ |
16 | 16 |
|
17 | 17 | import React from "react" |
18 | | -import prettyMillis from "pretty-ms" |
19 | 18 | import { EventEmitter } from "events" |
20 | 19 | import { Profiles } from "madwizard" |
21 | 20 | import { Loading } from "@kui-shell/plugin-client-common" |
22 | | -import { Grid, GridItem, Tile } from "@patternfly/react-core" |
23 | | - |
| 21 | +import { |
| 22 | + Card, |
| 23 | + CardTitle, |
| 24 | + CardBody, |
| 25 | + Title, |
| 26 | + Button, |
| 27 | + Flex, |
| 28 | + FlexItem, |
| 29 | + CardFooter, |
| 30 | + DescriptionList, |
| 31 | + DescriptionListGroup, |
| 32 | + DescriptionListTerm, |
| 33 | + DescriptionListDescription, |
| 34 | +} from "@patternfly/react-core" |
| 35 | + |
| 36 | +import ProfileSelect from "./ProfileSelect" |
| 37 | +import DashboardSelect from "./DashboardSelect" |
24 | 38 | import ProfileWatcher from "../tray/watchers/profile/list" |
| 39 | +import { handleBoot, handleShutdown } from "../controller/profile/actions" |
25 | 40 |
|
26 | | -import PlusIcon from "@patternfly/react-icons/dist/esm/icons/user-plus-icon" |
27 | | -// import ProfileIcon from "@patternfly/react-icons/dist/esm/icons/user-icon" |
| 41 | +import "../../web/scss/components/Dashboard/Description.scss" |
| 42 | +import "../../web/scss/components/ProfileExplorer/_index.scss" |
28 | 43 |
|
29 | 44 | const events = new EventEmitter() |
30 | 45 |
|
@@ -55,6 +70,9 @@ export default class ProfileExplorer extends React.PureComponent<Props, State> { |
55 | 70 | this.init() |
56 | 71 | } |
57 | 72 |
|
| 73 | + private readonly _handleBoot = handleBoot.bind(this) |
| 74 | + private readonly _handleShutdown = handleShutdown.bind(this) |
| 75 | + |
58 | 76 | private updateDebouncer: null | ReturnType<typeof setTimeout> = null |
59 | 77 |
|
60 | 78 | private readonly updateFn = () => { |
@@ -113,56 +131,85 @@ export default class ProfileExplorer extends React.PureComponent<Props, State> { |
113 | 131 | } |
114 | 132 | } |
115 | 133 |
|
116 | | - /** User has clicked to select a profile */ |
117 | | - private readonly onSelect = async (evt: React.MouseEvent<HTMLElement>) => { |
118 | | - const selectedProfile = evt.currentTarget.getAttribute("data-profile") |
119 | | - evt.currentTarget.scrollIntoView(true) |
120 | | - if (selectedProfile && selectedProfile !== this.state.selectedProfile) { |
121 | | - if (await Profiles.bumpLastUsedTime(selectedProfile)) { |
122 | | - emitSelectProfile(selectedProfile) |
123 | | - this.setState({ selectedProfile }) |
124 | | - } |
125 | | - } |
126 | | - } |
127 | | - |
128 | | - private prettyMillis(duration: number) { |
129 | | - if (duration < 1000) { |
130 | | - return "just now" |
131 | | - } else { |
132 | | - return prettyMillis(duration, { compact: true }) + " ago" |
133 | | - } |
134 | | - } |
135 | | - |
136 | 134 | public render() { |
137 | 135 | if (this.state && this.state.catastrophicError) { |
138 | 136 | return "Internal Error" |
139 | 137 | } else if (!this.state || !this.state.profiles) { |
140 | 138 | return <Loading /> |
141 | 139 | } else { |
142 | 140 | return ( |
143 | | - <Grid className="codeflare--gallery-grid flex-fill sans-serif top-pad left-pad right-pad bottom-pad" hasGutter> |
144 | | - {this.state.profiles.map((_) => ( |
145 | | - <GridItem key={_.name}> |
146 | | - <Tile |
147 | | - className="codeflare--tile" |
148 | | - data-profile={_.name} |
149 | | - title={_.name} |
150 | | - isSelected={this.state.selectedProfile === _.name} |
151 | | - onClick={this.onSelect} |
152 | | - > |
153 | | - {`Last used ${this.prettyMillis(Date.now() - _.lastUsedTime)}`} |
154 | | - </Tile> |
155 | | - </GridItem> |
156 | | - ))} |
157 | | - |
158 | | - { |
159 | | - <GridItem> |
160 | | - <Tile className="codeflare--tile codeflare--tile-new" title="New Profile" icon={<PlusIcon />} isDisabled> |
161 | | - Customize a profile |
162 | | - </Tile> |
163 | | - </GridItem> |
164 | | - } |
165 | | - </Grid> |
| 141 | + <Flex className="codeflare--profile-explorer flex-fill" direction={{ default: "column" }}> |
| 142 | + <FlexItem> |
| 143 | + <ProfileSelect selectedProfile={this.state.selectedProfile} profiles={this.state.profiles} /> |
| 144 | + </FlexItem> |
| 145 | + |
| 146 | + <FlexItem> |
| 147 | + <Card className="top-pad left-pad right-pad bottompad"> |
| 148 | + <CardTitle> |
| 149 | + <Flex> |
| 150 | + <FlexItem flex={{ default: "flex_1" }}> |
| 151 | + <Title headingLevel="h2" size="md"> |
| 152 | + {this.state.selectedProfile} |
| 153 | + </Title> |
| 154 | + </FlexItem> |
| 155 | + <FlexItem> |
| 156 | + <Title headingLevel="h2" size="md"> |
| 157 | + Status: pending |
| 158 | + </Title> |
| 159 | + </FlexItem> |
| 160 | + </Flex> |
| 161 | + </CardTitle> |
| 162 | + <CardBody> |
| 163 | + {/* TODO: Retrieve real data and abstract to its own component */} |
| 164 | + <DescriptionList className="codeflare--profile-explorer--description"> |
| 165 | + <DescriptionListGroup className="codeflare--profile-explorer--description--group"> |
| 166 | + <DescriptionListTerm>Cluster Context</DescriptionListTerm> |
| 167 | + <DescriptionListDescription> |
| 168 | + api-codeflare-train-v11-codeflare-openshift-com |
| 169 | + </DescriptionListDescription> |
| 170 | + </DescriptionListGroup> |
| 171 | + <DescriptionListGroup className="codeflare--profile-explorer--description--group"> |
| 172 | + <DescriptionListTerm>Cluster Namespace</DescriptionListTerm> |
| 173 | + <DescriptionListDescription>nvidia-gpu-operator</DescriptionListDescription> |
| 174 | + </DescriptionListGroup> |
| 175 | + <DescriptionListGroup className="codeflare--profile-explorer--description--group"> |
| 176 | + <DescriptionListTerm>Memory per Worker</DescriptionListTerm> |
| 177 | + <DescriptionListDescription>32Gi</DescriptionListDescription> |
| 178 | + </DescriptionListGroup> |
| 179 | + <DescriptionListGroup className="codeflare--profile-explorer--description--group"> |
| 180 | + <DescriptionListTerm>Worker Count</DescriptionListTerm> |
| 181 | + <DescriptionListDescription>4-4</DescriptionListDescription> |
| 182 | + </DescriptionListGroup> |
| 183 | + </DescriptionList> |
| 184 | + </CardBody> |
| 185 | + <CardFooter> |
| 186 | + <Flex> |
| 187 | + <FlexItem> |
| 188 | + <Button |
| 189 | + variant="primary" |
| 190 | + className="codeflare--profile-explorer--boot-btn" |
| 191 | + onClick={() => this._handleBoot(this.state.selectedProfile)} |
| 192 | + > |
| 193 | + Boot |
| 194 | + </Button> |
| 195 | + </FlexItem> |
| 196 | + <FlexItem> |
| 197 | + <Button |
| 198 | + variant="secondary" |
| 199 | + className="codeflare--profile-explorer--shutdown-btn" |
| 200 | + onClick={() => this._handleShutdown(this.state.selectedProfile)} |
| 201 | + > |
| 202 | + Shutdown |
| 203 | + </Button> |
| 204 | + </FlexItem> |
| 205 | + <FlexItem> |
| 206 | + <DashboardSelect selectedProfile={this.state.selectedProfile} /> |
| 207 | + </FlexItem> |
| 208 | + </Flex> |
| 209 | + </CardFooter> |
| 210 | + </Card> |
| 211 | + </FlexItem> |
| 212 | + </Flex> |
166 | 213 | ) |
167 | 214 | } |
168 | 215 | } |
|
0 commit comments