Merge pull request 'ui/sidebar: max-width of section, scroll within sections' (#5083) from ui/update-machine into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5083
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
.sidebar {
|
||||
@apply w-60 border-none z-10 h-full flex flex-col;
|
||||
@apply w-60 border-none z-10 h-full flex flex-col rounded-b-md overflow-hidden;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
div.sidebar-body {
|
||||
@apply py-4 px-2 h-full;
|
||||
@apply py-4 px-2;
|
||||
/* full - (y padding) */
|
||||
height: calc(100% - 2rem);
|
||||
|
||||
@apply border border-inv-3 rounded-bl-md rounded-br-md;
|
||||
|
||||
/* TODO: This is weird, we shouldn't disable native browser features, a11y impacts incomming */
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
|
||||
background:
|
||||
linear-gradient(0deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%),
|
||||
linear-gradient(
|
||||
@@ -20,13 +21,14 @@ div.sidebar-body {
|
||||
@apply backdrop-blur-sm;
|
||||
|
||||
.accordion {
|
||||
@apply w-full mb-4;
|
||||
@apply w-full mb-4 h-full flex flex-col justify-start gap-4;
|
||||
|
||||
&:last-child {
|
||||
@apply mb-0;
|
||||
}
|
||||
|
||||
& > .item {
|
||||
max-height: 50%;
|
||||
&:last-child {
|
||||
@apply mb-0;
|
||||
}
|
||||
@@ -58,9 +60,13 @@ div.sidebar-body {
|
||||
}
|
||||
|
||||
& > .content {
|
||||
@apply overflow-hidden flex flex-col;
|
||||
@apply flex flex-col;
|
||||
@apply py-3 px-1.5 bg-inv-4 rounded-md mb-4;
|
||||
|
||||
max-height: calc(100% - 24px);
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
|
||||
animation: slideAccordionUp 300ms cubic-bezier(0.87, 0, 0.13, 1);
|
||||
|
||||
&[data-expanded] {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useMachineStateQuery } from "@/src/hooks/queries";
|
||||
import { SidebarProps } from "./Sidebar";
|
||||
import { Button } from "../Button/Button";
|
||||
import { useClanContext } from "@/src/routes/Clan/Clan";
|
||||
import { Instance } from "@/src/workflows/Service/models";
|
||||
|
||||
interface MachineProps {
|
||||
clanURI: string;
|
||||
@@ -129,22 +130,42 @@ const Machines = () => {
|
||||
|
||||
export const ServiceRoute = (props: {
|
||||
clanURI: string;
|
||||
machineName?: string;
|
||||
label: string;
|
||||
id: string;
|
||||
module: { input?: string | null | undefined; name: string };
|
||||
instance: Instance;
|
||||
}) => (
|
||||
<A href={buildServicePath(props)} replace={true}>
|
||||
<A
|
||||
href={buildServicePath({
|
||||
clanURI: props.clanURI,
|
||||
id: props.id,
|
||||
module: props.instance.module,
|
||||
})}
|
||||
replace={true}
|
||||
>
|
||||
<div class="flex w-full flex-col gap-2">
|
||||
<Typography
|
||||
hierarchy="label"
|
||||
size="s"
|
||||
weight="bold"
|
||||
color="primary"
|
||||
inverted
|
||||
>
|
||||
{props.label}
|
||||
</Typography>
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<Typography
|
||||
hierarchy="label"
|
||||
size="xs"
|
||||
weight="bold"
|
||||
color="primary"
|
||||
inverted
|
||||
>
|
||||
{props.id}
|
||||
</Typography>
|
||||
</div>
|
||||
<div class="flex w-full flex-row items-center gap-1">
|
||||
<Icon icon="Code" size="0.75rem" inverted color="tertiary" />
|
||||
<Typography
|
||||
hierarchy="label"
|
||||
family="mono"
|
||||
size="s"
|
||||
inverted
|
||||
color="primary"
|
||||
>
|
||||
{props.instance.resolved.usage_ref.name}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</A>
|
||||
);
|
||||
@@ -165,8 +186,12 @@ const Services = () => {
|
||||
const moduleName = instance.module.name;
|
||||
|
||||
const label = moduleName == id ? moduleName : `${moduleName} (${id})`;
|
||||
|
||||
return { id, label, module: instance.module };
|
||||
console.log("Service instance", id, instance, label);
|
||||
return {
|
||||
id,
|
||||
label,
|
||||
instance: instance,
|
||||
};
|
||||
},
|
||||
);
|
||||
};
|
||||
@@ -191,7 +216,14 @@ const Services = () => {
|
||||
<Accordion.Content class="content">
|
||||
<nav>
|
||||
<For each={serviceInstances()}>
|
||||
{(instance) => <ServiceRoute clanURI={ctx.clanURI} {...instance} />}
|
||||
{(mapped) => (
|
||||
<ServiceRoute
|
||||
clanURI={ctx.clanURI}
|
||||
id={mapped.id}
|
||||
label={mapped.label}
|
||||
instance={mapped.instance}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
</nav>
|
||||
</Accordion.Content>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useMachineName } from "@/src/hooks/clan";
|
||||
import { useMachineStateQuery } from "@/src/hooks/queries";
|
||||
import styles from "./SidebarSectionInstall.module.css";
|
||||
import { Alert } from "../Alert/Alert";
|
||||
import { useClanContext } from "@/src/routes/Clan/Clan";
|
||||
|
||||
export interface SidebarSectionInstallProps {
|
||||
clanURI: string;
|
||||
@@ -12,8 +13,8 @@ export interface SidebarSectionInstallProps {
|
||||
}
|
||||
|
||||
export const SidebarSectionInstall = (props: SidebarSectionInstallProps) => {
|
||||
const ctx = useClanContext();
|
||||
const query = useMachineStateQuery(props.clanURI, props.machineName);
|
||||
|
||||
const [showInstall, setShowModal] = createSignal(false);
|
||||
|
||||
return (
|
||||
@@ -32,7 +33,12 @@ export const SidebarSectionInstall = (props: SidebarSectionInstallProps) => {
|
||||
<InstallModal
|
||||
open={showInstall()}
|
||||
machineName={useMachineName()}
|
||||
onClose={() => setShowModal(false)}
|
||||
onClose={async () => {
|
||||
// refresh some queries
|
||||
ctx.machinesQuery.refetch();
|
||||
ctx.serviceInstancesQuery.refetch();
|
||||
setShowModal(false);
|
||||
}}
|
||||
/>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useMachineName } from "@/src/hooks/clan";
|
||||
import { useMachineStateQuery } from "@/src/hooks/queries";
|
||||
import styles from "./SidebarSectionInstall.module.css";
|
||||
import { UpdateModal } from "@/src/workflows/InstallMachine/UpdateMachine";
|
||||
import { useClanContext } from "@/src/routes/Clan/Clan";
|
||||
|
||||
export interface SidebarSectionUpdateProps {
|
||||
clanURI: string;
|
||||
@@ -11,6 +12,7 @@ export interface SidebarSectionUpdateProps {
|
||||
}
|
||||
|
||||
export const SidebarSectionUpdate = (props: SidebarSectionUpdateProps) => {
|
||||
const ctx = useClanContext();
|
||||
const query = useMachineStateQuery(props.clanURI, props.machineName);
|
||||
|
||||
const [showUpdate, setShowUpdate] = createSignal(false);
|
||||
@@ -29,7 +31,13 @@ export const SidebarSectionUpdate = (props: SidebarSectionUpdateProps) => {
|
||||
<UpdateModal
|
||||
open={showUpdate()}
|
||||
machineName={useMachineName()}
|
||||
onClose={() => setShowUpdate(false)}
|
||||
onClose={async () => {
|
||||
// refresh some queries
|
||||
ctx.machinesQuery.refetch();
|
||||
ctx.serviceInstancesQuery.refetch();
|
||||
|
||||
setShowUpdate(false);
|
||||
}}
|
||||
/>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
@@ -20,14 +20,15 @@ export const SectionServices = () => {
|
||||
|
||||
return (ctx.machinesQuery.data[machineName].instance_refs ?? []).map(
|
||||
(id) => {
|
||||
const module = ctx.serviceInstancesQuery.data?.[id].module;
|
||||
if (!module) {
|
||||
throw new Error(`Service instance ${id} has no module`);
|
||||
const instance = ctx.serviceInstancesQuery.data?.[id];
|
||||
if (!instance) {
|
||||
throw new Error(`Service instance ${id} not found`);
|
||||
}
|
||||
const module = instance.module;
|
||||
|
||||
return {
|
||||
id,
|
||||
module,
|
||||
instance,
|
||||
label: module.name == id ? module.name : `${module.name} (${id})`,
|
||||
};
|
||||
},
|
||||
@@ -41,11 +42,7 @@ export const SectionServices = () => {
|
||||
<nav>
|
||||
<For each={services()}>
|
||||
{(instance) => (
|
||||
<ServiceRoute
|
||||
clanURI={ctx.clanURI}
|
||||
machineName={useMachineName()}
|
||||
{...instance}
|
||||
/>
|
||||
<ServiceRoute clanURI={ctx.clanURI} {...instance} />
|
||||
)}
|
||||
</For>
|
||||
</nav>
|
||||
|
||||
@@ -13,7 +13,6 @@ import { installSteps } from "./steps/installSteps";
|
||||
import { ApiCall } from "@/src/hooks/api";
|
||||
|
||||
import cx from "classnames";
|
||||
import { useClanContext } from "@/src/routes/Clan/Clan";
|
||||
|
||||
interface InstallStepperProps {
|
||||
onDone: () => void;
|
||||
@@ -67,8 +66,6 @@ export interface InstallStoreType {
|
||||
export type PromptValues = Record<string, Record<string, string>>;
|
||||
|
||||
export const InstallModal = (props: InstallModalProps) => {
|
||||
const ctx = useClanContext();
|
||||
|
||||
const stepper = createStepper(
|
||||
{
|
||||
steps,
|
||||
@@ -111,10 +108,6 @@ export const InstallModal = (props: InstallModalProps) => {
|
||||
};
|
||||
|
||||
const onClose = async () => {
|
||||
// refresh some queries
|
||||
await ctx.machinesQuery.refetch();
|
||||
await ctx.serviceInstancesQuery.refetch();
|
||||
|
||||
props.onClose?.();
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import { LoadingBar } from "@/src/components/LoadingBar/LoadingBar";
|
||||
import { useApiClient } from "@/src/hooks/ApiClient";
|
||||
import { useClanURI } from "@/src/hooks/clan";
|
||||
import { AlertProps } from "@/src/components/Alert/Alert";
|
||||
import { useClanContext } from "@/src/routes/Clan/Clan";
|
||||
|
||||
// TODO: Deduplicate
|
||||
interface UpdateStepperProps {
|
||||
@@ -238,8 +237,6 @@ export type UpdateSteps = typeof steps;
|
||||
export type PromptValues = Record<string, Record<string, string>>;
|
||||
|
||||
export const UpdateModal = (props: UpdateModalProps) => {
|
||||
const ctx = useClanContext();
|
||||
|
||||
const stepper = createStepper(
|
||||
{
|
||||
steps,
|
||||
@@ -285,10 +282,6 @@ export const UpdateModal = (props: UpdateModalProps) => {
|
||||
};
|
||||
|
||||
const onClose = async () => {
|
||||
// refresh some queries
|
||||
await ctx.machinesQuery.refetch();
|
||||
await ctx.serviceInstancesQuery.refetch();
|
||||
|
||||
props.onClose?.();
|
||||
};
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ export interface Module {
|
||||
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export type Instance = ValueOf<NonNullable<ServiceInstancesQuery["data"]>>;
|
||||
|
||||
/**
|
||||
* Collect all members (machines and tags) for a given role in a service instance
|
||||
*
|
||||
@@ -50,7 +52,7 @@ type ValueOf<T> = T[keyof T];
|
||||
*
|
||||
*/
|
||||
export function getRoleMembers(
|
||||
instance: ValueOf<NonNullable<ServiceInstancesQuery["data"]>>,
|
||||
instance: Instance,
|
||||
all_machines: NonNullable<MachinesQuery["data"]>,
|
||||
role: string,
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user