10 changed files with 189 additions and 82 deletions
@ -0,0 +1,78 @@ |
|||
import type React from "react"; |
|||
import { useState } from "react"; |
|||
|
|||
import { |
|||
Heading, |
|||
IconComponent, |
|||
majorScale, |
|||
Pane, |
|||
Paragraph, |
|||
Tab, |
|||
Tablist, |
|||
} from "evergreen-ui"; |
|||
import type { IconType } from "react-icons"; |
|||
|
|||
export interface TabType { |
|||
name: string; |
|||
icon: IconComponent | IconType; |
|||
element: () => JSX.Element; |
|||
disabled?: boolean; |
|||
} |
|||
|
|||
export interface SlideSheetTabbedContentProps { |
|||
heading: string; |
|||
description: string; |
|||
tabs: TabType[]; |
|||
} |
|||
|
|||
export const SlideSheetTabbedContent = ({ |
|||
heading, |
|||
description, |
|||
tabs, |
|||
}: SlideSheetTabbedContentProps): JSX.Element => { |
|||
const [selectedTab, setSelectedTab] = useState(0); |
|||
|
|||
return ( |
|||
<> |
|||
<Pane zIndex={1} flexShrink={0} elevation={1} backgroundColor="white"> |
|||
<Pane padding={16} borderBottom="muted"> |
|||
<Heading size={600}>{heading}</Heading> |
|||
<Paragraph size={400} color="muted"> |
|||
{description} |
|||
</Paragraph> |
|||
</Pane> |
|||
<Pane display="flex" padding={8}> |
|||
<Tablist> |
|||
{tabs.map((Entry, index) => ( |
|||
<Tab |
|||
key={index} |
|||
userSelect="none" |
|||
disabled={Entry.disabled} |
|||
gap={5} |
|||
onSelect={() => setSelectedTab(index)} |
|||
isSelected={selectedTab === index} |
|||
> |
|||
<Entry.icon /> |
|||
{Entry.name} |
|||
</Tab> |
|||
))} |
|||
</Tablist> |
|||
</Pane> |
|||
</Pane> |
|||
<Pane display="flex" overflowY="scroll" background="tint1" padding={16}> |
|||
{tabs.map((Entry, index) => ( |
|||
<Pane |
|||
key={index} |
|||
borderRadius={majorScale(1)} |
|||
backgroundColor="white" |
|||
elevation={1} |
|||
flexGrow={1} |
|||
display={selectedTab === index ? "block" : "none"} |
|||
> |
|||
{!Entry.disabled && <Entry.element />} |
|||
</Pane> |
|||
))} |
|||
</Pane> |
|||
</> |
|||
); |
|||
}; |
|||
@ -0,0 +1,56 @@ |
|||
import type React from "react"; |
|||
import { useState } from "react"; |
|||
|
|||
import { Pane, Tab, Tablist } from "evergreen-ui"; |
|||
|
|||
import { ExternalNotification } from "@app/components/PageComponents/ModuleConfig/ExternalNotification.js"; |
|||
import { MQTT } from "@components/PageComponents/ModuleConfig/MQTT.js"; |
|||
import { Serial } from "@components/PageComponents/ModuleConfig/Serial.js"; |
|||
|
|||
export const AppConfig = (): JSX.Element => { |
|||
const [selectedIndex, setSelectedIndex] = useState(0); |
|||
|
|||
const configSections = [ |
|||
{ |
|||
label: "Interface", |
|||
element: MQTT, |
|||
}, |
|||
{ |
|||
label: "Logging", |
|||
element: Serial, |
|||
}, |
|||
{ |
|||
label: "Language", |
|||
element: ExternalNotification, |
|||
}, |
|||
]; |
|||
|
|||
return ( |
|||
<Pane display="flex"> |
|||
<Pane flexBasis={150} marginRight={24}> |
|||
<Tablist> |
|||
{configSections.map((Config, index) => ( |
|||
<Tab |
|||
key={index} |
|||
direction="vertical" |
|||
isSelected={index === selectedIndex} |
|||
onSelect={() => setSelectedIndex(index)} |
|||
> |
|||
{Config.label} |
|||
</Tab> |
|||
))} |
|||
</Tablist> |
|||
</Pane> |
|||
<Pane flex="1"> |
|||
{configSections.map((Config, index) => ( |
|||
<Pane |
|||
key={index} |
|||
display={index === selectedIndex ? "block" : "none"} |
|||
> |
|||
<Config.element /> |
|||
</Pane> |
|||
))} |
|||
</Pane> |
|||
</Pane> |
|||
); |
|||
}; |
|||
@ -1,36 +1,31 @@ |
|||
import type React from "react"; |
|||
import { useState } from "react"; |
|||
|
|||
import { CogIcon, CubeIcon } from "evergreen-ui"; |
|||
import { ApplicationsIcon, CogIcon, CubeIcon } from "evergreen-ui"; |
|||
|
|||
import { Tab, TabbedContent } from "@components/layout/page/TabbedContent"; |
|||
import { TabbedContent, TabType } from "@components/layout/page/TabbedContent"; |
|||
|
|||
import { AppConfig } from "./AppConfig.js"; |
|||
import { DeviceConfig } from "./DeviceConfig.js"; |
|||
import { ModuleConfig } from "./ModuleConfig.js"; |
|||
|
|||
export const ConfigPage = (): JSX.Element => { |
|||
const [activeConfig, setActiveConfig] = useState(0); |
|||
|
|||
const tabs: Tab[] = [ |
|||
const tabs: TabType[] = [ |
|||
{ |
|||
key: 0, |
|||
name: "Device Config", |
|||
icon: CogIcon, |
|||
element: DeviceConfig, |
|||
}, |
|||
{ |
|||
key: 1, |
|||
name: "Module Config", |
|||
icon: CubeIcon, |
|||
element: ModuleConfig, |
|||
}, |
|||
{ |
|||
name: "App Config", |
|||
icon: ApplicationsIcon, |
|||
element: AppConfig, |
|||
}, |
|||
]; |
|||
|
|||
return ( |
|||
<TabbedContent |
|||
active={activeConfig} |
|||
setActive={setActiveConfig} |
|||
tabs={tabs} |
|||
/> |
|||
); |
|||
return <TabbedContent tabs={tabs} />; |
|||
}; |
|||
|
|||
@ -1,46 +1,35 @@ |
|||
import type React from "react"; |
|||
import { useState } from "react"; |
|||
|
|||
import { DocumentIcon, GanttChartIcon, RainIcon } from "evergreen-ui"; |
|||
|
|||
import { useDevice } from "@app/core/stores/deviceStore.js"; |
|||
import { Tab, TabbedContent } from "@components/layout/page/TabbedContent"; |
|||
import { TabbedContent, TabType } from "@components/layout/page/TabbedContent"; |
|||
import { FileBrowser } from "@pages/Extensions/FileBrowser"; |
|||
|
|||
import { Environment } from "./Environment.js"; |
|||
|
|||
export const ExtensionsPage = (): JSX.Element => { |
|||
const [activeExtension, setActiveExtension] = useState(0); |
|||
const { hardware } = useDevice(); |
|||
|
|||
const tabs: Tab[] = [ |
|||
const tabs: TabType[] = [ |
|||
{ |
|||
key: 0, |
|||
name: "File Browser", |
|||
icon: DocumentIcon, |
|||
element: FileBrowser, |
|||
disabled: !hardware.hasWifi, |
|||
}, |
|||
{ |
|||
key: 1, |
|||
name: "Range Test", |
|||
icon: GanttChartIcon, |
|||
element: FileBrowser, |
|||
disabled: !hardware.hasWifi, |
|||
}, |
|||
{ |
|||
key: 2, |
|||
name: "Environment", |
|||
icon: RainIcon, |
|||
element: Environment, |
|||
}, |
|||
]; |
|||
|
|||
return ( |
|||
<TabbedContent |
|||
active={activeExtension} |
|||
setActive={setActiveExtension} |
|||
tabs={tabs} |
|||
/> |
|||
); |
|||
return <TabbedContent tabs={tabs} />; |
|||
}; |
|||
|
|||
Loading…
Reference in new issue