Features: Add group nesting/subgroups
This commit is contained in:
parent
5ee2ea559c
commit
4fa024bca6
@ -21,6 +21,25 @@ Groups are defined as top-level array entries.
|
||||
|
||||
<img width="1038" alt="Service Groups" src="https://user-images.githubusercontent.com/82196/187040754-28065242-4534-4409-881c-93d1921c6141.png">
|
||||
|
||||
## Subgroups
|
||||
|
||||
Subgroups are defined as array entries with `type: group` and an array `services: ...`,
|
||||
|
||||
```
|
||||
- Group A:
|
||||
- Subgroup A:
|
||||
type: group
|
||||
services:
|
||||
- Service A:
|
||||
href: http://localhost/
|
||||
- Service B:
|
||||
href: http://localhost/
|
||||
|
||||
- Group B:
|
||||
- Service C:
|
||||
href: http://localhost/
|
||||
```
|
||||
|
||||
## Services
|
||||
|
||||
Services are defined as array entries on groups,
|
||||
|
||||
@ -8,12 +8,14 @@ import ResolvedIcon from "components/resolvedicon";
|
||||
|
||||
export default function ServicesGroup({
|
||||
group,
|
||||
subgroups,
|
||||
services,
|
||||
layout,
|
||||
fiveColumns,
|
||||
disableCollapse,
|
||||
useEqualHeights,
|
||||
groupsInitiallyCollapsed,
|
||||
isSubgroup = false,
|
||||
}) {
|
||||
const panel = useRef();
|
||||
|
||||
@ -29,6 +31,7 @@ export default function ServicesGroup({
|
||||
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
|
||||
layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "",
|
||||
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1",
|
||||
isSubgroup === false ? "" : "bg-theme-500/20 dark:bg-white/5 rounded-md px-2 py-2",
|
||||
)}
|
||||
>
|
||||
<Disclosure defaultOpen={!(layout?.initiallyCollapsed ?? groupsInitiallyCollapsed) ?? true}>
|
||||
@ -74,7 +77,13 @@ export default function ServicesGroup({
|
||||
}}
|
||||
>
|
||||
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
|
||||
<List group={group} services={services.services} layout={layout} useEqualHeights={useEqualHeights} />
|
||||
<List
|
||||
group={group}
|
||||
subgroups={subgroups}
|
||||
services={services.services}
|
||||
layout={layout}
|
||||
useEqualHeights={useEqualHeights}
|
||||
/>
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
|
||||
@ -3,9 +3,11 @@ import classNames from "classnames";
|
||||
import { columnMap } from "../../utils/layout/columns";
|
||||
|
||||
import Item from "components/services/item";
|
||||
import Group from "components/services/group";
|
||||
|
||||
export default function List({ group, services, layout, useEqualHeights }) {
|
||||
export default function List({ group, subgroups = [], services, layout, useEqualHeights }) {
|
||||
return (
|
||||
<>
|
||||
<ul
|
||||
className={classNames(
|
||||
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
|
||||
@ -21,5 +23,17 @@ export default function List({ group, services, layout, useEqualHeights }) {
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
{subgroups
|
||||
.filter((subgroup) => subgroup != [])
|
||||
.map((subgroup) => (
|
||||
<Group
|
||||
group={subgroup}
|
||||
services={subgroup}
|
||||
layout={layout}
|
||||
useEqualHeights={useEqualHeights}
|
||||
isSubgroup={true}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -292,6 +292,7 @@ function Home({ initialSettings }) {
|
||||
<ServicesGroup
|
||||
key={group.name}
|
||||
group={group.name}
|
||||
subgroups={group.subgroups}
|
||||
services={group}
|
||||
layout={settings.layout?.[group.name]}
|
||||
fiveColumns={settings.fiveColumns}
|
||||
@ -317,6 +318,7 @@ function Home({ initialSettings }) {
|
||||
<ServicesGroup
|
||||
key={group.name}
|
||||
group={group.name}
|
||||
subgroups={group.subgroups}
|
||||
services={group}
|
||||
layout={settings.layout?.[group.name]}
|
||||
fiveColumns={settings.fiveColumns}
|
||||
|
||||
@ -142,9 +142,11 @@ export async function servicesResponse() {
|
||||
mergedGroupsNames.forEach((groupName) => {
|
||||
const discoveredDockerGroup = discoveredDockerServices.find((group) => group.name === groupName) || {
|
||||
services: [],
|
||||
subgroups: [],
|
||||
};
|
||||
const discoveredKubernetesGroup = discoveredKubernetesServices.find((group) => group.name === groupName) || {
|
||||
services: [],
|
||||
subgroups: [],
|
||||
};
|
||||
const configuredGroup = configuredServices.find((group) => group.name === groupName) || { services: [] };
|
||||
|
||||
@ -153,6 +155,11 @@ export async function servicesResponse() {
|
||||
services: [...discoveredDockerGroup.services, ...discoveredKubernetesGroup.services, ...configuredGroup.services]
|
||||
.filter((service) => service)
|
||||
.sort(compareServices),
|
||||
subgroups: [
|
||||
...discoveredDockerGroup.subgroups,
|
||||
...discoveredKubernetesGroup.subgroups,
|
||||
...configuredGroup.subgroups,
|
||||
].filter((subgroup) => subgroup),
|
||||
};
|
||||
|
||||
if (definedLayouts) {
|
||||
|
||||
@ -25,24 +25,22 @@ export async function servicesFromConfig() {
|
||||
return [];
|
||||
}
|
||||
|
||||
// map easy to write YAML objects into easy to consume JS arrays
|
||||
const servicesArray = services.map((servicesGroup) => ({
|
||||
const mappingFunc = (servicesGroup, servicesArr = servicesGroup[Object.keys(servicesGroup)[0]]) => ({
|
||||
name: Object.keys(servicesGroup)[0],
|
||||
services: servicesGroup[Object.keys(servicesGroup)[0]].map((entries) => ({
|
||||
services: servicesArr
|
||||
.filter((entry) => entry[Object.keys(entry)[0]].type != "group")
|
||||
.map((entries, entryIndex) => ({
|
||||
name: Object.keys(entries)[0],
|
||||
weight: (entryIndex + 1) * 100,
|
||||
type: entries[Object.keys(entries)[0]].type ? entries[Object.keys(entries)[0]].type : "service",
|
||||
...entries[Object.keys(entries)[0]],
|
||||
type: "service",
|
||||
})),
|
||||
}));
|
||||
|
||||
// add default weight to services based on their position in the configuration
|
||||
servicesArray.forEach((group, groupIndex) => {
|
||||
group.services.forEach((service, serviceIndex) => {
|
||||
if (service.weight === undefined) {
|
||||
servicesArray[groupIndex].services[serviceIndex].weight = (serviceIndex + 1) * 100;
|
||||
}
|
||||
});
|
||||
subgroups: servicesArr
|
||||
.filter((entry) => entry[Object.keys(entry)[0]].type == "group")
|
||||
.map((entries) => mappingFunc(entries, entries[Object.keys(entries)[0]].services)),
|
||||
});
|
||||
// map easy to write YAML objects into easy to consume JS arrays
|
||||
const servicesArray = services.map((servicesGroup) => mappingFunc(servicesGroup));
|
||||
|
||||
return servicesArray;
|
||||
}
|
||||
@ -134,6 +132,7 @@ export async function servicesFromDocker() {
|
||||
mappedServiceGroups.push({
|
||||
name: serverService.group,
|
||||
services: [],
|
||||
subgroups: [],
|
||||
});
|
||||
serverGroup = mappedServiceGroups[mappedServiceGroups.length - 1];
|
||||
}
|
||||
@ -317,6 +316,7 @@ export async function servicesFromKubernetes() {
|
||||
mappedServiceGroups.push({
|
||||
name: serverService.group,
|
||||
services: [],
|
||||
subgroups: [],
|
||||
});
|
||||
serverGroup = mappedServiceGroups[mappedServiceGroups.length - 1];
|
||||
}
|
||||
@ -338,7 +338,7 @@ export async function servicesFromKubernetes() {
|
||||
}
|
||||
|
||||
export function cleanServiceGroups(groups) {
|
||||
return groups.map((serviceGroup) => ({
|
||||
const cleanerFunc = (serviceGroup) => ({
|
||||
name: serviceGroup.name,
|
||||
services: serviceGroup.services.map((service) => {
|
||||
const cleanedService = { ...service };
|
||||
@ -663,7 +663,9 @@ export function cleanServiceGroups(groups) {
|
||||
|
||||
return cleanedService;
|
||||
}),
|
||||
}));
|
||||
subgroups: serviceGroup.subgroups.map((serviceGroup) => cleanerFunc(serviceGroup)),
|
||||
});
|
||||
return groups.map((serviceGroup) => cleanerFunc(serviceGroup));
|
||||
}
|
||||
|
||||
export async function getServiceItem(group, service) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user