Skip to content

Commit ea6aefd

Browse files
committed
feat: allow callers to provide null guidebook to terminal, and show EmptyState if so
1 parent e4cc00a commit ea6aefd

File tree

1 file changed

+74
-16
lines changed

1 file changed

+74
-16
lines changed

Diff for: plugins/plugin-codeflare/src/controller/terminal.tsx

+74-16
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515
*/
1616

1717
import React from "react"
18-
import { Allotment } from "allotment"
18+
import { Allotment, AllotmentHandle } from "allotment"
1919
import { Loading } from "@kui-shell/plugin-client-common"
2020
import { Arguments, encodeComponent } from "@kui-shell/core"
2121
import { defaultGuidebook as defaultGuidebookFromClient } from "@kui-shell/client/config.d/client.json"
22+
import { Button, EmptyState, EmptyStateBody, EmptyStatePrimary, Title, Tooltip } from "@patternfly/react-core"
2223

2324
import respawn from "./respawn"
2425

@@ -55,8 +56,8 @@ export async function shell(args: Arguments) {
5556
}
5657

5758
export type Props = Pick<BaseProps, "tab" | "REPL" | "onExit" | "searchable" | "fontSizeAdjust"> & {
58-
/** Default guidebook (if not given, we will take the value from the client definition) */
59-
defaultGuidebook?: string
59+
/** Default guidebook (if not given, we will take the value from the client definition); `null` means do not show anything */
60+
defaultGuidebook?: string | null
6061

6162
/** Run guidebook in non-interactive mode? */
6263
defaultNoninteractive?: boolean
@@ -79,7 +80,7 @@ type State = Partial<Pick<BaseProps, "cmdline" | "env">> & {
7980
error?: boolean
8081

8182
/** Use this guidebook in the terminal execution */
82-
guidebook?: string
83+
guidebook?: string | null
8384

8485
/** Any extra env vars to add to the guidebook execution. These will be pre-joined with the default env. */
8586
extraEnv?: BaseProps["env"]
@@ -99,15 +100,19 @@ export class TaskTerminal extends React.PureComponent<Props, State> {
99100
private readonly splits = {
100101
horizontal: [25, 75],
101102
vertical1: [100], // no `this.props.aboveTerminal`
102-
vertical2: [60, 40], // yes
103+
vertical2a: [60, 40], // yes, and show a guidebook
104+
vertical2b: [80, 20], // yes, and do not show a guidebook
103105
}
104106

105107
private readonly tasks = [{ label: "Run a Job", argv: ["codeflare", "-p", "${SELECTED_PROFILE}"] }]
106108

107109
public constructor(props: Props) {
108110
super(props)
109111

110-
this.state = { initCount: 0, guidebook: defaultGuidebookFromClient }
112+
this.state = {
113+
initCount: 0,
114+
guidebook: props.defaultGuidebook === null ? null : props.defaultGuidebook || defaultGuidebookFromClient,
115+
}
111116
this.init()
112117
}
113118

@@ -119,6 +124,10 @@ export class TaskTerminal extends React.PureComponent<Props, State> {
119124
private async init() {
120125
const guidebook = this.state.guidebook
121126

127+
if (guidebook === null) {
128+
return
129+
}
130+
122131
try {
123132
// respawn, meaning launch it with codeflare
124133
const { argv, env } = await respawn(this.tasks[0].argv)
@@ -187,15 +196,34 @@ export class TaskTerminal extends React.PureComponent<Props, State> {
187196

188197
public componentDidUpdate(prevProps: Props, prevState: State) {
189198
if (prevState.guidebook !== this.state.guidebook || prevState.ifor !== this.state.ifor) {
199+
if (prevState.guidebook === null) {
200+
this.allotmentRef.current?.reset()
201+
}
190202
this.init()
191203
}
192204
}
193205

206+
private readonly _refresh = () => {
207+
this.setState({ guidebook: this.props.defaultGuidebook || defaultGuidebookFromClient })
208+
}
209+
210+
private get vertical1() {
211+
return this.splits.vertical1
212+
}
213+
214+
private get vertical2() {
215+
return !this.state.cmdline || !this.state.env ? this.splits.vertical2b : this.splits.vertical2a
216+
}
217+
218+
private noGuidebook() {
219+
return <Empty refresh={this._refresh} />
220+
}
221+
222+
private readonly allotmentRef = React.createRef<AllotmentHandle>()
223+
194224
public render() {
195225
if (this.state.error) {
196226
return "Internal Error"
197-
} else if (!this.state.cmdline || !this.state.env) {
198-
return <Loading />
199227
}
200228

201229
return (
@@ -209,18 +237,23 @@ export class TaskTerminal extends React.PureComponent<Props, State> {
209237
) : (
210238
<Allotment
211239
vertical
212-
defaultSizes={!this.props.aboveTerminal ? this.splits.vertical1 : this.splits.vertical2}
240+
defaultSizes={!this.props.aboveTerminal ? this.vertical1 : this.vertical2}
213241
snap
242+
ref={this.allotmentRef}
214243
>
215244
{this.props.aboveTerminal && <AllotmentFillPane>{this.props.aboveTerminal}</AllotmentFillPane>}
216245
<AllotmentFillPane>
217-
<SelectedProfileTerminal
218-
key={this.state.initCount + "_" + this.state.cmdline + "-" + this.state.selectedProfile}
219-
cmdline={this.state.cmdline}
220-
env={this.state.env}
221-
{...this.props}
222-
selectedProfile={this.state.selectedProfile}
223-
/>
246+
{!this.state.cmdline || !this.state.env ? (
247+
this.noGuidebook()
248+
) : (
249+
<SelectedProfileTerminal
250+
key={this.state.initCount + "_" + this.state.cmdline + "-" + this.state.selectedProfile}
251+
cmdline={this.state.cmdline}
252+
env={this.state.env}
253+
{...this.props}
254+
selectedProfile={this.state.selectedProfile}
255+
/>
256+
)}
224257
</AllotmentFillPane>
225258
</Allotment>
226259
)}
@@ -230,6 +263,31 @@ export class TaskTerminal extends React.PureComponent<Props, State> {
230263
}
231264
}
232265

266+
class Empty extends React.PureComponent<{ refresh(): void }> {
267+
/** Run through all questions again */
268+
private resubmit() {
269+
return (
270+
<Tooltip content="Force a run through all constraints">
271+
<Button variant="primary" onClick={this.props.refresh}>
272+
Walk through the constraints again
273+
</Button>
274+
</Tooltip>
275+
)
276+
}
277+
278+
public render() {
279+
return (
280+
<EmptyState variant="xs" className="sans-serif flex-fill codeflare--workload-comparo">
281+
<Title size="lg" headingLevel="h4">
282+
All constraints satisfied
283+
</Title>
284+
<EmptyStateBody>Click here to walk through all of the constraints</EmptyStateBody>
285+
<EmptyStatePrimary>{this.resubmit()}</EmptyStatePrimary>
286+
</EmptyState>
287+
)
288+
}
289+
}
290+
233291
/**
234292
* This is a command handler that opens up a terminal to run a selected profile-oriented task */
235293
export function task(args: Arguments) {

0 commit comments

Comments
 (0)