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 { showNotification, updateNotification } from '@mantine/notifications';
|
||||||
import {
|
import {
|
||||||
IconCheck,
|
IconCheck,
|
||||||
IconLicense,
|
|
||||||
IconPlayerPlay,
|
IconPlayerPlay,
|
||||||
IconPlayerStop,
|
IconPlayerStop,
|
||||||
IconPlus,
|
IconPlus,
|
||||||
@@ -13,8 +13,9 @@ import {
|
|||||||
} from '@tabler/icons';
|
} from '@tabler/icons';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Dockerode from 'dockerode';
|
import Dockerode from 'dockerode';
|
||||||
import addToHomarr from '../../tools/addToHomarr';
|
import addToHomarr, { tryMatchService } from '../../tools/addToHomarr';
|
||||||
import { useConfig } from '../../tools/state';
|
import { useConfig } from '../../tools/state';
|
||||||
|
import { AddAppShelfItemForm } from '../AppShelf/AddAppShelfItem';
|
||||||
|
|
||||||
function sendDockerCommand(action: string, containerId: string, containerName: string) {
|
function sendDockerCommand(action: string, containerId: string, containerName: string) {
|
||||||
showNotification({
|
showNotification({
|
||||||
@@ -57,8 +58,22 @@ export interface ContainerActionBarProps {
|
|||||||
|
|
||||||
export default function ContainerActionBar({ selected, reload }: ContainerActionBarProps) {
|
export default function ContainerActionBar({ selected, reload }: ContainerActionBarProps) {
|
||||||
const { config, setConfig } = useConfig();
|
const { config, setConfig } = useConfig();
|
||||||
|
const [opened, setOpened] = useBooleanToggle(false);
|
||||||
return (
|
return (
|
||||||
<Group>
|
<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
|
<Button
|
||||||
leftIcon={<IconRotateClockwise />}
|
leftIcon={<IconRotateClockwise />}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -79,7 +94,11 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
Promise.all(
|
Promise.all(
|
||||||
selected.map((container) => {
|
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({
|
return showNotification({
|
||||||
id: container.Id,
|
id: container.Id,
|
||||||
title: `Failed to stop ${container.Names[0].substring(1)}`,
|
title: `Failed to stop ${container.Names[0].substring(1)}`,
|
||||||
@@ -120,11 +139,18 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
|
|||||||
color="indigo"
|
color="indigo"
|
||||||
variant="light"
|
variant="light"
|
||||||
radius="md"
|
radius="md"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
Promise.all(selected.map((container) => addToHomarr(container, config, setConfig))).then(
|
if (selected.length !== 1) {
|
||||||
() => reload()
|
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
|
Add to Homarr
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export default function DockerDrawer(props: any) {
|
|||||||
<Drawer opened={opened} onClose={() => setOpened(false)} padding="xl" size="full">
|
<Drawer opened={opened} onClose={() => setOpened(false)} padding="xl" size="full">
|
||||||
<ContainerActionBar selected={selection} reload={reload} />
|
<ContainerActionBar selected={selection} reload={reload} />
|
||||||
<div style={{ position: 'relative' }}>
|
<div style={{ position: 'relative' }}>
|
||||||
<LoadingOverlay visible={visible} />
|
<LoadingOverlay transitionDuration={500} visible={visible} />
|
||||||
<DockerTable containers={containers} selection={selection} setSelection={setSelection} />
|
<DockerTable containers={containers} selection={selection} setSelection={setSelection} />
|
||||||
</div>
|
</div>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
import { showNotification } from '@mantine/notifications';
|
||||||
import Dockerode from 'dockerode';
|
import Dockerode from 'dockerode';
|
||||||
import { Config } from './types';
|
import { Config, MatchingImages, ServiceType, ServiceTypeList } from './types';
|
||||||
|
|
||||||
async function MatchIcon(name: string) {
|
async function MatchIcon(name: string) {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
@@ -10,12 +11,30 @@ async function MatchIcon(name: string) {
|
|||||||
return res.ok ? res.url : '/favicon.svg';
|
return res.ok ? res.url : '/favicon.svg';
|
||||||
}
|
}
|
||||||
|
|
||||||
function tryMatchType(imageName: string) {
|
function tryMatchType(imageName: string): ServiceType {
|
||||||
// Search for a match with the Image name from the MATCH_TYPES array
|
// Try to find imageName inside MatchingImages
|
||||||
console.log(`Trying to match type for: ${imageName}`);
|
|
||||||
|
const match = MatchingImages.find(({ image }) => imageName.includes(image));
|
||||||
|
if (match) {
|
||||||
|
return match.type;
|
||||||
|
}
|
||||||
return 'Other';
|
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(
|
export default async function addToHomarr(
|
||||||
container: Dockerode.ContainerInfo,
|
container: Dockerode.ContainerInfo,
|
||||||
config: Config,
|
config: Config,
|
||||||
@@ -29,7 +48,7 @@ export default async function addToHomarr(
|
|||||||
name: container.Names[0].substring(1),
|
name: container.Names[0].substring(1),
|
||||||
id: container.Id,
|
id: container.Id,
|
||||||
type: tryMatchType(container.Image),
|
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)),
|
icon: await MatchIcon(container.Names[0].substring(1)),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -82,6 +82,12 @@ export type ServiceType =
|
|||||||
| 'qBittorrent'
|
| 'qBittorrent'
|
||||||
| 'Transmission';
|
| '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 {
|
export interface serviceItem {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user