mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 15:35:55 +01:00
✨ Add simple image name matching
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { Button, Group } from '@mantine/core';
|
||||
import { Button, Group, Modal, Text, Title } from '@mantine/core';
|
||||
import { useBooleanToggle } from '@mantine/hooks';
|
||||
import { showNotification, updateNotification } from '@mantine/notifications';
|
||||
import {
|
||||
IconCheck,
|
||||
IconLicense,
|
||||
IconPlayerPlay,
|
||||
IconPlayerStop,
|
||||
IconPlus,
|
||||
@@ -13,8 +13,9 @@ import {
|
||||
} from '@tabler/icons';
|
||||
import axios from 'axios';
|
||||
import Dockerode from 'dockerode';
|
||||
import addToHomarr from '../../tools/addToHomarr';
|
||||
import addToHomarr, { tryMatchService } from '../../tools/addToHomarr';
|
||||
import { useConfig } from '../../tools/state';
|
||||
import { AddAppShelfItemForm } from '../AppShelf/AddAppShelfItem';
|
||||
|
||||
function sendDockerCommand(action: string, containerId: string, containerName: string) {
|
||||
showNotification({
|
||||
@@ -57,8 +58,22 @@ export interface ContainerActionBarProps {
|
||||
|
||||
export default function ContainerActionBar({ selected, reload }: ContainerActionBarProps) {
|
||||
const { config, setConfig } = useConfig();
|
||||
const [opened, setOpened] = useBooleanToggle(false);
|
||||
return (
|
||||
<Group>
|
||||
<Modal
|
||||
size="xl"
|
||||
radius="md"
|
||||
opened={opened}
|
||||
onClose={() => setOpened(false)}
|
||||
title="Add service"
|
||||
>
|
||||
<AddAppShelfItemForm
|
||||
setOpened={setOpened}
|
||||
{...tryMatchService(selected.at(0))}
|
||||
message="Add service to homarr"
|
||||
/>
|
||||
</Modal>
|
||||
<Button
|
||||
leftIcon={<IconRotateClockwise />}
|
||||
onClick={() =>
|
||||
@@ -79,7 +94,11 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
|
||||
onClick={() =>
|
||||
Promise.all(
|
||||
selected.map((container) => {
|
||||
if (container.State === 'stopped' || container.State === 'created' || container.State === 'exited') {
|
||||
if (
|
||||
container.State === 'stopped' ||
|
||||
container.State === 'created' ||
|
||||
container.State === 'exited'
|
||||
) {
|
||||
return showNotification({
|
||||
id: container.Id,
|
||||
title: `Failed to stop ${container.Names[0].substring(1)}`,
|
||||
@@ -120,11 +139,18 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
|
||||
color="indigo"
|
||||
variant="light"
|
||||
radius="md"
|
||||
onClick={() =>
|
||||
Promise.all(selected.map((container) => addToHomarr(container, config, setConfig))).then(
|
||||
() => reload()
|
||||
)
|
||||
onClick={() => {
|
||||
if (selected.length !== 1) {
|
||||
showNotification({
|
||||
autoClose: 5000,
|
||||
title: <Title order={4}>Please only add one service at a time!</Title>,
|
||||
color: 'red',
|
||||
message: undefined,
|
||||
});
|
||||
} else {
|
||||
setOpened(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Add to Homarr
|
||||
</Button>
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function DockerDrawer(props: any) {
|
||||
<Drawer opened={opened} onClose={() => setOpened(false)} padding="xl" size="full">
|
||||
<ContainerActionBar selected={selection} reload={reload} />
|
||||
<div style={{ position: 'relative' }}>
|
||||
<LoadingOverlay visible={visible} />
|
||||
<LoadingOverlay transitionDuration={500} visible={visible} />
|
||||
<DockerTable containers={containers} selection={selection} setSelection={setSelection} />
|
||||
</div>
|
||||
</Drawer>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import Dockerode from 'dockerode';
|
||||
import { Config } from './types';
|
||||
import { Config, MatchingImages, ServiceType, ServiceTypeList } from './types';
|
||||
|
||||
async function MatchIcon(name: string) {
|
||||
const res = await fetch(
|
||||
@@ -10,12 +11,30 @@ async function MatchIcon(name: string) {
|
||||
return res.ok ? res.url : '/favicon.svg';
|
||||
}
|
||||
|
||||
function tryMatchType(imageName: string) {
|
||||
// Search for a match with the Image name from the MATCH_TYPES array
|
||||
console.log(`Trying to match type for: ${imageName}`);
|
||||
function tryMatchType(imageName: string): ServiceType {
|
||||
// Try to find imageName inside MatchingImages
|
||||
|
||||
const match = MatchingImages.find(({ image }) => imageName.includes(image));
|
||||
if (match) {
|
||||
return match.type;
|
||||
}
|
||||
return 'Other';
|
||||
}
|
||||
|
||||
export function tryMatchService(container: Dockerode.ContainerInfo | undefined) {
|
||||
if (container === undefined) return {};
|
||||
const name = container.Names[0].substring(1);
|
||||
return {
|
||||
name,
|
||||
id: container.Id,
|
||||
type: tryMatchType(container.Image),
|
||||
url: `${container.Ports.at(0)?.IP}:${container.Ports.at(0)?.PublicPort}`,
|
||||
icon: `https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/${name
|
||||
.replace(/\s+/g, '-')
|
||||
.toLowerCase()}.png`,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function addToHomarr(
|
||||
container: Dockerode.ContainerInfo,
|
||||
config: Config,
|
||||
@@ -29,7 +48,7 @@ export default async function addToHomarr(
|
||||
name: container.Names[0].substring(1),
|
||||
id: container.Id,
|
||||
type: tryMatchType(container.Image),
|
||||
url: `${container.Ports.at(0)?.IP}:${container.Ports.at(0)?.PublicPort}`,
|
||||
url: `localhost:${container.Ports.at(0)?.PublicPort}`,
|
||||
icon: await MatchIcon(container.Names[0].substring(1)),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -82,6 +82,12 @@ export type ServiceType =
|
||||
| 'qBittorrent'
|
||||
| 'Transmission';
|
||||
|
||||
export const MatchingImages: { image: string; type: ServiceType }[] = [
|
||||
{ image: 'lscr.io/linuxserver/radarr', type: 'Radarr' },
|
||||
{ image: 'lscr.io/linuxserver/sonarr', type: 'Sonarr' },
|
||||
{ image: 'lscr.io/linuxserver/qbittorrent', type: 'qBittorrent' },
|
||||
];
|
||||
|
||||
export interface serviceItem {
|
||||
id: string;
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user