Browse Source

Add commit sha to footer. (#636)

* feat: added commit sha to footer.

* added translation

* added padding

* updated styling
pull/637/head
Dan Ditomaso 1 year ago
committed by GitHub
parent
commit
df036d3904
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      package.json
  2. 229
      src/components/DeviceInfoPanel.tsx
  3. 2
      src/components/PageLayout.tsx
  4. 4
      src/components/Sidebar.tsx
  5. 13
      src/components/UI/Footer.tsx
  6. 4
      src/components/UI/Sidebar/SidebarButton.tsx
  7. 3
      src/i18n/locales/en/ui.json

2
package.json

@ -11,7 +11,7 @@
"lint:fix": "deno lint --fix src/", "lint:fix": "deno lint --fix src/",
"format": "deno fmt src/", "format": "deno fmt src/",
"dev": "deno task dev:ui", "dev": "deno task dev:ui",
"dev:ui": "deno run -A npm:vite dev", "dev:ui": "VITE_APP_VERSION=development deno run -A npm:vite dev",
"test": "deno run -A npm:vitest", "test": "deno run -A npm:vitest",
"preview": "deno run -A npm:vite preview", "preview": "deno run -A npm:vite preview",
"package": "gzipper c -i html,js,css,png,ico,svg,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ ." "package": "gzipper c -i html,js,css,png,ico,svg,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ ."

229
src/components/DeviceInfoPanel.tsx

@ -2,7 +2,7 @@ import { cn } from "@core/utils/cn.ts";
import { import {
CpuIcon, CpuIcon,
Languages, Languages,
LucideIcon, type LucideIcon,
Palette, Palette,
PenLine, PenLine,
Search as SearchIcon, Search as SearchIcon,
@ -11,7 +11,7 @@ import {
import BatteryStatus from "./BatteryStatus.tsx"; import BatteryStatus from "./BatteryStatus.tsx";
import { Subtle } from "./UI/Typography/Subtle.tsx"; import { Subtle } from "./UI/Typography/Subtle.tsx";
import { Avatar } from "./UI/Avatar.tsx"; import { Avatar } from "./UI/Avatar.tsx";
import { DeviceMetrics } from "./types.ts"; import type { DeviceMetrics } from "./types.ts";
import { Button } from "./UI/Button.tsx"; import { Button } from "./UI/Button.tsx";
import React, { Fragment } from "react"; import React, { Fragment } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@ -110,131 +110,130 @@ export const DeviceInfoPanel = ({
]; ];
return ( return (
<div className="p-1"> <>
<div className="flex flex-col"> <div
<div className={cn(
className={cn( "flex items-center gap-3 p-1 flex-shrink-0",
"flex items-center gap-3 p-1", isCollapsed && "justify-center",
isCollapsed && "justify-center", )}
)} >
> <Avatar
<Avatar text={user.shortName}
text={user.shortName} className={cn("flex-shrink-0", isCollapsed && "")}
className={cn("flex-shrink-0", isCollapsed && "")} size="sm"
size="sm" />
/>
{!isCollapsed && (
<p
className={cn(
"text-sm font-medium text-gray-800 dark:text-gray-200",
"transition-opacity duration-300 ease-in-out",
)}
>
{user.longName}
</p>
)}
</div>
{!isCollapsed && ( {!isCollapsed && (
<div className="my-2 h-px bg-gray-200 dark:bg-gray-700"></div> <p
className={cn(
"text-sm font-medium text-gray-800 dark:text-gray-200",
"transition-opacity duration-300 ease-in-out truncate",
)}
>
{user.longName}
</p>
)} )}
</div>
<div {!isCollapsed && (
className={cn( <div className="my-2 h-px bg-gray-200 dark:bg-gray-700 flex-shrink-0">
"flex flex-col gap-2 mt-1",
"transition-all duration-300 ease-in-out",
isCollapsed
? "opacity-0 max-w-0 h-0 invisible pointer-events-none"
: "opacity-100 max-w-xs h-auto visible",
)}
>
{deviceInfoItems.map((item) => {
const IconComponent = item.icon;
return (
<div
key={item.id}
className="flex items-center gap-2.5 text-sm"
>
{IconComponent && (
<IconComponent
size={16}
className="text-gray-500 dark:text-gray-400 w-4 flex-shrink-0"
/>
)}
{item.customComponent}
{item.id !== "battery" && (
<Subtle className="text-gray-600 dark:text-gray-300">
{item.label}: {item.value}
</Subtle>
)}
</div>
);
})}
</div> </div>
)}
{!isCollapsed && ( <div
<div className="my-2 h-px bg-gray-200 dark:bg-gray-700"></div> className={cn(
"flex flex-col gap-2 mt-1",
"transition-all duration-300 ease-in-out",
isCollapsed
? "opacity-0 max-w-0 h-0 invisible pointer-events-none"
: "opacity-100 max-w-xs h-auto visible",
)} )}
>
{deviceInfoItems.map((item) => {
const IconComponent = item.icon;
return (
<div
key={item.id}
className="flex items-center gap-2.5 text-sm"
>
{IconComponent && (
<IconComponent
size={16}
className="text-gray-500 dark:text-gray-400 w-4 flex-shrink-0"
/>
)}
{item.customComponent}
{item.id !== "battery" && (
<Subtle className="text-gray-600 dark:text-gray-300">
{item.label}: {item.value}
</Subtle>
)}
</div>
);
})}
</div>
<div {!isCollapsed && (
className={cn( <div className="my-2 h-px bg-gray-200 dark:bg-gray-700 flex-shrink-0">
"flex flex-col gap-1 mt-1", </div>
"transition-all duration-300 ease-in-out", )}
isCollapsed
? "opacity-0 max-w-0 h-0 invisible pointer-events-none" <div
: "opacity-100 max-w-xs visible", className={cn(
)} "flex flex-col gap-1 mt-1",
> "transition-all duration-300 ease-in-out",
{actionButtons.map((buttonItem) => { isCollapsed
const Icon = buttonItem.icon; ? "opacity-0 max-w-0 h-0 invisible pointer-events-none"
if (buttonItem.render) { : "opacity-100 max-w-xs visible",
return ( )}
<Fragment key={buttonItem.id}> >
{buttonItem.render()} {actionButtons.map((buttonItem) => {
</Fragment> const Icon = buttonItem.icon;
); if (buttonItem.render) {
}
return ( return (
<Button <Fragment key={buttonItem.id}>
key={buttonItem.id} {buttonItem.render()}
variant="ghost" </Fragment>
aria-label={buttonItem.label} );
onClick={buttonItem.onClick} }
return (
<Button
key={buttonItem.id}
variant="ghost"
aria-label={buttonItem.label}
onClick={buttonItem.onClick}
className={cn(
"group",
"flex w-full items-center justify-start text-sm p-1.5 rounded-md",
"gap-2.5",
"transition-colors duration-150",
!disableHover && "hover:bg-gray-100 dark:hover:bg-gray-700",
)}
>
<Icon
size={16}
className={cn( className={cn(
"group", "flex-shrink-0 w-4",
"flex w-full items-center justify-start text-sm p-1.5 rounded-md", "text-gray-500 dark:text-gray-400",
"gap-2.5",
"transition-colors duration-150", "transition-colors duration-150",
!disableHover && "hover:bg-gray-100 dark:hover:bg-gray-700", !disableHover &&
"group-hover:text-gray-700 dark:group-hover:text-gray-200",
)}
/>
<Subtle
className={cn(
"text-sm",
"text-gray-600 dark:text-gray-300",
"transition-colors duration-150",
!disableHover &&
"group-hover:text-gray-800 dark:group-hover:text-gray-100",
)} )}
> >
<Icon {buttonItem.label}
size={16} </Subtle>
className={cn( </Button>
"flex-shrink-0 w-4", );
"text-gray-500 dark:text-gray-400", })}
"transition-colors duration-150",
!disableHover &&
"group-hover:text-gray-700 dark:group-hover:text-gray-200",
)}
/>
<Subtle
className={cn(
"text-sm",
"text-gray-600 dark:text-gray-300",
"transition-colors duration-150",
!disableHover &&
"group-hover:text-gray-800 dark:group-hover:text-gray-100",
)}
>
{buttonItem.label}
</Subtle>
</Button>
);
})}
{/* <Code>{import.meta.env.COMMIT_HASH}</Code> */}
</div>
</div> </div>
</div> </>
); );
}; };

2
src/components/PageLayout.tsx

@ -111,7 +111,7 @@ export const PageLayout = ({
{rightBar && ( {rightBar && (
<aside <aside
className={cn( className={cn(
"w-48 lg:w-[270px] shrink-0 border-l border-slate-300 dark:border-slate-700 px-2 overflow-hidden", "w-56 lg:w-[270px] text-balance shrink-0 border-l border-slate-300 dark:border-slate-700 px-2 overflow-hidden",
rightBarClassName, rightBarClassName,
)} )}
> >

4
src/components/Sidebar.tsx

@ -128,7 +128,7 @@ export const Sidebar = ({ children }: SidebarProps) => {
className={cn( className={cn(
"relative border-slate-300 dark:border-slate-700", "relative border-slate-300 dark:border-slate-700",
"transition-all duration-300 ease-in-out flex-shrink-0", "transition-all duration-300 ease-in-out flex-shrink-0",
isCollapsed ? "w-24" : "w-46 lg:w-64", isCollapsed ? "w-24" : "w-52 lg:w-64",
)} )}
> >
<CollapseToggleButton /> <CollapseToggleButton />
@ -188,7 +188,7 @@ export const Sidebar = ({ children }: SidebarProps) => {
{children} {children}
</div> </div>
<div className="pt-4 border-t-[0.5px] bg-background-primary border-slate-300 dark:border-slate-700 flex-shrink-0"> <div className=" pt-4 border-t-[0.5px] bg-background-primary border-slate-300 dark:border-slate-700 h-full flex-1">
{myNode === undefined {myNode === undefined
? ( ? (
<div className="flex flex-col items-center justify-center py-6"> <div className="flex flex-col items-center justify-center py-6">

13
src/components/UI/Footer.tsx

@ -1,11 +1,13 @@
import { cn } from "@core/utils/cn.ts"; import { cn } from "@core/utils/cn.ts";
import { Trans } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
type FooterProps = { type FooterProps = {
className?: string; className?: string;
}; };
const Footer = ({ className, ...props }: FooterProps) => { const Footer = ({ className, ...props }: FooterProps) => {
const { t } = useTranslation();
return ( return (
<footer <footer
className={cn( className={cn(
@ -14,7 +16,14 @@ const Footer = ({ className, ...props }: FooterProps) => {
)} )}
{...props} {...props}
> >
<p> <div className="justify-start px-2">
<span className="font-semibold text-gray-500/40 dark:text-gray-400/40">
{t("footer.commitSha", {
sha: String(import.meta.env.VITE_COMMIT_HASH)?.toUpperCase(),
})}
</span>
</div>
<p className="ml-auto mr-auto text-gray-500 dark:text-gray-400">
<Trans <Trans
i18nKey="footer.text" i18nKey="footer.text"
components={[ components={[

4
src/components/UI/Sidebar/SidebarButton.tsx

@ -52,13 +52,13 @@ export const SidebarButton = ({
<span <span
className={cn( className={cn(
"flex flex-wrap justify-start text-left text-wrap break-all", "flex flex-wrap justify-start text-left text-balance break-all",
"min-w-0", "min-w-0",
"px-1", "px-1",
"transition-all duration-300 ease-in-out", "transition-all duration-300 ease-in-out",
isButtonCollapsed isButtonCollapsed
? "opacity-0 max-w-0 invisible w-0 overflow-hidden" ? "opacity-0 max-w-0 invisible w-0 overflow-hidden"
: "opacity-100 max-w-full visible flex-1 whitespace-normal", : "opacity-100 max-w-full visible whitespace-normal",
)} )}
> >
{label} {label}

3
src/i18n/locales/en/ui.json

@ -157,6 +157,7 @@
"changeTheme": "Change Color Scheme" "changeTheme": "Change Color Scheme"
}, },
"footer": { "footer": {
"text": "Powered by <0>▲ Vercel</0> | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information</1>" "text": "Powered by <0>▲ Vercel</0> | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information</1>",
"commitSha": "Commit SHA: {{sha}}"
} }
} }

Loading…
Cancel
Save