Skip to content

Commit daedbe7

Browse files
committed
feat: test page works
1 parent a3669d8 commit daedbe7

File tree

5 files changed

+223
-69
lines changed

5 files changed

+223
-69
lines changed

examples/gauge/Components/Input.tsx

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
1-
import { ComponentProps, DisplayComponent, FSComponent, Subscribable, UUID, VNode } from "@microsoft/msfs-sdk"
1+
import {
2+
ComponentProps,
3+
DisplayComponent,
4+
FSComponent,
5+
Subscribable,
6+
SubscribableUtils,
7+
UUID,
8+
VNode,
9+
} from "@microsoft/msfs-sdk"
10+
import { Button, InterfaceNavbarItemV2 } from "./Utils"
211

312
interface InputProps extends ComponentProps {
4-
value?: string
13+
value: Subscribable<string>
14+
setValue: (value: string) => void
15+
default?: Subscribable<string> | string
516
class?: string | Subscribable<string>
617
textarea?: boolean
718
}
@@ -10,13 +21,16 @@ export class Input extends DisplayComponent<InputProps> {
1021
private readonly inputId = UUID.GenerateUuid()
1122
private readonly inputRef = FSComponent.createRef<HTMLInputElement>()
1223

13-
get value() {
14-
return this.inputRef.instance.value
15-
}
16-
1724
onAfterRender(node: VNode): void {
1825
super.onAfterRender(node)
1926

27+
this.props.value.map(val => (this.inputRef.instance.value = val))
28+
SubscribableUtils.toSubscribable(this.props.default ?? "", true).map(val => {
29+
this.inputRef.instance.placeholder = val
30+
})
31+
32+
this.inputRef.instance.addEventListener("input", () => this.props.setValue(this.inputRef.instance.value ?? ""))
33+
2034
this.inputRef.instance.onfocus = this.onInputFocus
2135
this.inputRef.instance.onblur = this.onInputBlur
2236
}
@@ -54,3 +68,32 @@ export class Input extends DisplayComponent<InputProps> {
5468
return <input ref={this.inputRef} {...this.getInputProps()} />
5569
}
5670
}
71+
72+
interface CheckboxProps extends ComponentProps {
73+
value: Subscribable<string>
74+
setValue: (value: string) => void
75+
default?: Subscribable<string> | string
76+
class?: string
77+
}
78+
79+
export class Checkbox extends DisplayComponent<CheckboxProps> {
80+
private readonly isActive = this.props.value.map(val => (val == "true" ? true : false))
81+
82+
private onClick = () => {
83+
this.props.setValue(this.isActive.get() ? "false" : "true")
84+
}
85+
86+
render(): VNode {
87+
return (
88+
<InterfaceNavbarItemV2
89+
content={""}
90+
active={this.isActive}
91+
class={`h-full flex-grow bg-white text-black flex items-center justify-center ${this.props.class ?? ""}`}
92+
activeClass="!bg-green-400 !text-white"
93+
setActive={() => this.onClick()}
94+
>
95+
<span class="text-4xl">{this.isActive.map(val => (val ? "✔" : "X"))}</span>
96+
</InterfaceNavbarItemV2>
97+
)
98+
}
99+
}

examples/gauge/Components/InterfaceSample.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export class InterfaceSample extends DisplayComponent<InterfaceSampleProps> {
7272
interface={this.navigationDataInterface}
7373
/>,
7474
],
75-
[1, <TestPage />],
75+
[1, <TestPage interface={this.navigationDataInterface} />],
7676
[
7777
2,
7878
<AuthPage

examples/gauge/Components/Pages/Dashboard/Dashboard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export class Dashboard extends DisplayComponent<DashboardProps> {
7171
<div class="w-1/3 flex flex-col">
7272
<p class="ml-2 text-3xl mb-4">Databases</p>
7373
<div class="mt-2 flex-grow bg-ng-background-500 shadow-inner">
74-
<div class="flex flex-col space-y-2">
74+
<div class="flex flex-col space-y-2 overflow-auto">
7575
<List
7676
data={this.props.databases}
7777
renderItem={(data, index) => this.displayItems(data as PackageInfo, index)}

examples/gauge/Components/Pages/Test/Test.tsx

Lines changed: 161 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
VNode,
99
} from "@microsoft/msfs-sdk"
1010
import { NavigraphNavigationDataInterface } from "@navigraph/msfs-navigation-data-interface"
11-
import { InterfaceNavbarItemV2, InterfaceSwitch } from "../../Utils"
11+
import { Checkbox, Input } from "../../Input"
12+
import { Button, InterfaceNavbarItemV2, InterfaceSwitch } from "../../Utils"
1213

1314
interface TestPageProps extends ComponentProps {
1415
interface: NavigraphNavigationDataInterface
@@ -18,12 +19,13 @@ interface FunctionDescriptor {
1819
index: number
1920
arguments: string[]
2021
name: string
21-
functionCallback: (input?: string, inputAlt?: string) => unknown
22+
functionCallback: (input?: string, inputAlt?: string) => Promise<unknown>
2223
}
2324

2425
interface InputState {
2526
active: boolean
2627
type: InputStateType
28+
hint: string
2729
}
2830

2931
enum InputStateType {
@@ -32,24 +34,10 @@ enum InputStateType {
3234
}
3335

3436
export class TestPage extends DisplayComponent<TestPageProps> {
35-
private readonly selectedFunction = Subject.create(0)
36-
private readonly input1State = ObjectSubject.create<InputState>({
37-
active: false,
38-
type: InputStateType.String,
39-
})
40-
private readonly input2State = ObjectSubject.create<InputState>({
41-
active: false,
42-
type: InputStateType.String,
43-
})
44-
45-
private strToBool(input?: string): boolean {
46-
return input == "true" ? true : false
47-
}
48-
4937
private readonly functionList: FunctionDescriptor[] = [
5038
{
5139
index: 0,
52-
arguments: ["url: string"],
40+
arguments: ["url: string", "activate: bool"],
5341
name: "DownloadNavigationData",
5442
functionCallback: input => this.props.interface.download_navigation_data(input ?? ""),
5543
},
@@ -74,50 +62,101 @@ export class TestPage extends DisplayComponent<TestPageProps> {
7462
},
7563
]
7664

77-
private readonly _generateInputs = this.selectedFunction.map(selectedFunction => {
78-
const functionObj = this.functionList[selectedFunction]
65+
private readonly input1 = Subject.create("")
66+
private readonly input2 = Subject.create("")
67+
private readonly output = Subject.create("")
68+
private readonly selectedFunction = Subject.create(0)
69+
private readonly selectedFunctionObj = this.selectedFunction.map(index => this.functionList[index])
70+
private readonly input1State = ObjectSubject.create<InputState>({
71+
active: false,
72+
type: InputStateType.String,
73+
hint: this.functionList[this.selectedFunction.get()].arguments[0] ?? "",
74+
})
75+
private readonly input2State = ObjectSubject.create<InputState>({
76+
active: false,
77+
type: InputStateType.String,
78+
hint: this.functionList[this.selectedFunction.get()].arguments[1] ?? "",
79+
})
7980

80-
const functionArgCount = functionObj.arguments.length
81+
private doubleInputCss = MappedSubject.create(
82+
([input1, input2]) =>
83+
`flex flex-row h-16 bg-ng-background-500 items-center p-2 ${input1.active && input2.active ? "space-x-2" : ""}`,
84+
this.input1State,
85+
this.input2State,
86+
)
8187

82-
switch (functionArgCount) {
83-
case 1: {
84-
this.input1State.set("active", true)
85-
this.input2State.set("active", false)
86-
break
87-
}
88-
case 2: {
89-
this.input1State.set("active", true)
90-
this.input2State.set("active", true)
91-
break
92-
}
93-
default: {
94-
this.input1State.set("active", false)
95-
this.input2State.set("active", false)
96-
break
97-
}
98-
}
88+
private strToBool(input?: string): boolean {
89+
return input == "true" ? true : false
90+
}
91+
92+
private handleFunction = () => {
93+
const functionObj = this.selectedFunctionObj.get()
94+
const input1 = this.input1.get()
95+
const input2 = this.input2.get()
96+
97+
functionObj
98+
.functionCallback(input1, input2)
99+
.then(obj => this.output.set(JSON.stringify(obj, null, 2)))
100+
.catch(err => this.output.set(JSON.stringify(err, null, 2)))
101+
}
102+
103+
onAfterRender(node: VNode): void {
104+
super.onAfterRender(node)
99105

100-
functionObj.arguments.forEach((value, index) => {
101-
const argumentType = value.includes("bool") ? InputStateType.Bool : InputStateType.String
106+
this.selectedFunctionObj.map(functionObj => {
107+
const functionArgCount = functionObj.arguments.length
102108

103-
switch (index) {
109+
switch (functionArgCount) {
104110
case 1: {
105-
this.input2State.set("type", argumentType)
111+
this.input1State.set("active", true)
112+
this.input2State.set("active", false)
113+
break
114+
}
115+
case 2: {
116+
this.input1State.set("active", true)
117+
this.input2State.set("active", true)
106118
break
107119
}
108120
default: {
109-
this.input1State.set("type", argumentType)
121+
this.input1State.set("active", false)
122+
this.input2State.set("active", false)
110123
break
111124
}
112125
}
126+
127+
this.input1.set("")
128+
this.input2.set("")
129+
130+
functionObj.arguments.forEach((value, index) => {
131+
const argumentType = value.includes("bool") ? InputStateType.Bool : InputStateType.String
132+
133+
switch (index) {
134+
case 1: {
135+
this.input2State.set("type", argumentType)
136+
this.input2State.set("hint", functionObj.arguments[1])
137+
if (argumentType === InputStateType.Bool) {
138+
this.input2.set("false")
139+
}
140+
break
141+
}
142+
default: {
143+
this.input1State.set("type", argumentType)
144+
this.input1State.set("hint", functionObj.arguments[0])
145+
if (argumentType === InputStateType.Bool) {
146+
this.input1.set("false")
147+
}
148+
break
149+
}
150+
}
151+
})
113152
})
114-
})
153+
}
115154

116155
render(): VNode {
117156
return (
118157
<div class="size-full flex flex-col">
119158
<p class="mb-8 text-4xl">Test</p>
120-
<div class="flex flex-row">
159+
<div class="size-full flex flex-row flex-grow">
121160
<div class="w-1/3 flex flex-col">
122161
<div class="overflow-scroll flex-grow bg-ng-background-500">
123162
{this.functionList.map(obj => (
@@ -133,30 +172,94 @@ export class TestPage extends DisplayComponent<TestPageProps> {
133172
</InterfaceNavbarItemV2>
134173
))}
135174
</div>
136-
<div class="flex flex-row">
175+
<div class={this.doubleInputCss}>
137176
<InterfaceSwitch
138-
active={this.input1State.map(obj => {
139-
return obj.active ? (obj.type === InputStateType.String ? 0 : 1) : 2
140-
})}
177+
intoNoTheming
178+
class="flex content-center"
179+
intoClass="flex-grow flex"
180+
active={this.input1State.map(obj => (obj.active ? (obj.type === InputStateType.String ? 0 : 1) : 2))}
141181
pages={[
142-
[0, <p class="text-xl">String</p>],
143-
[1, <p class="text-xl">Bool</p>],
144-
[2, <p class="text-xl">None</p>],
182+
[
183+
0,
184+
<Input
185+
class="text-xl text-black px-1 size-full"
186+
value={this.input1}
187+
setValue={value => this.input1.set(value)}
188+
default={this.input1State.map(obj => obj.hint)}
189+
/>,
190+
],
191+
[
192+
1,
193+
<div class="flex-grow flex flex-row space-x-2 items-center justify-center">
194+
<p class="text-2xl">{this.input1State.map(obj => obj.hint.split(":")[0] + ":")}</p>
195+
<Checkbox value={this.input1} setValue={value => this.input1.set(value)} />
196+
</div>,
197+
],
198+
[
199+
2,
200+
<div class="flex-grow flex items-center justify-center">
201+
<span class="text-2xl">No Inputs</span>
202+
</div>,
203+
],
145204
]}
146205
/>
147206
<InterfaceSwitch
148-
active={this.input2State.map(obj => {
149-
return obj.active ? (obj.type === InputStateType.String ? 0 : 1) : 2
150-
})}
207+
noTheming
208+
intoNoTheming
209+
hideLast
210+
class={this.input2State.map(obj => (obj.active ? "size-full flex content-center" : ""))}
211+
intoClass="flex-grow flex content-center"
212+
active={this.input2State.map(obj => (obj.active ? (obj.type === InputStateType.String ? 0 : 1) : 2))}
151213
pages={[
152-
[0, <p class="text-xl">String</p>],
153-
[1, <p class="text-xl">Bool</p>],
154-
[2, <p class="text-xl">None</p>],
214+
[
215+
0,
216+
<Input
217+
class="text-xl text-black px-1"
218+
value={this.input2}
219+
setValue={value => this.input2.set(value)}
220+
default={this.input2State.map(obj => obj.hint)}
221+
/>,
222+
],
223+
[
224+
1,
225+
<div class="flex-grow flex flex-row space-x-2 items-center justify-center">
226+
<p class="text-2xl">{this.input2State.map(obj => obj.hint.split(":")[0] + ":")}</p>
227+
<Checkbox value={this.input2} setValue={value => this.input2.set(value)} />
228+
</div>,
229+
],
230+
[2, <></>],
155231
]}
156232
/>
157233
</div>
158234
</div>
159-
<div class="w-2/3 bg-ng-background-700"></div>
235+
<div class="w-2/3 bg-ng-background-700 flex flex-col">
236+
<div class="size-full p-2 flex-grow overflow-auto">
237+
<p class="text-xl whitespace-pre">{this.output}</p>
238+
</div>
239+
<Button
240+
class="h-16 flex flex-row items-center pl-4 bg-blue-400 overflow-auto"
241+
onClick={() => this.handleFunction()}
242+
>
243+
<span class="text-3xl">Try:</span>
244+
<span class="text-2xl pl-4 whitespace-pre">
245+
{MappedSubject.create(
246+
([obj, input1, input2, input1State, input2State]) =>
247+
`${obj.name}(${
248+
input1State.active ? (input1State.type === InputStateType.String ? `"${input1}"` : input1) : ""
249+
}${
250+
input2State.active
251+
? `, ${input2State.type === InputStateType.String ? `"${input2}"` : input2}`
252+
: ""
253+
})`,
254+
this.selectedFunctionObj,
255+
this.input1,
256+
this.input2,
257+
this.input1State,
258+
this.input2State,
259+
)}
260+
</span>
261+
</Button>
262+
</div>
160263
</div>
161264
</div>
162265
)

0 commit comments

Comments
 (0)