Merge branch 'manuel-rw-gridstack' into gridstack-wip-meierschlumpf

This commit is contained in:
Meierschlumpf
2023-01-07 17:59:43 +01:00
56 changed files with 962 additions and 785 deletions

View File

@@ -36,7 +36,7 @@ export const IconSelector = ({ onChange, allowAppNamePropagation, form }: IconSe
const { data, isLoading } = useRepositoryIconsQuery<WalkxcodeRepositoryIcon>({
url: 'https://api.github.com/repos/walkxcode/Dashboard-Icons/contents/png',
converter: (item) => ({
url: `https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${item.name}`,
url: `https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/${item.name}`,
fileName: item.name,
}),
});

View File

@@ -9,15 +9,21 @@ import {
Stack,
ThemeIcon,
Title,
Text,
Badge,
Tooltip,
} from '@mantine/core';
import { TablerIcon } from '@tabler/icons';
import { useTranslation } from 'next-i18next';
import { useState } from 'react';
import { AppIntegrationPropertyAccessabilityType } from '../../../../../../../../types/app';
interface GenericSecretInputProps {
label: string;
value: string;
setIcon: TablerIcon;
secretIsPresent: boolean;
type: AppIntegrationPropertyAccessabilityType;
onClickUpdateButton: (value: string | undefined) => void;
}
@@ -25,6 +31,8 @@ export const GenericSecretInput = ({
label,
value,
setIcon,
secretIsPresent,
type,
onClickUpdateButton,
...props
}: GenericSecretInputProps) => {
@@ -36,17 +44,61 @@ export const GenericSecretInput = ({
const { t } = useTranslation(['layout/modals/add-app', 'common']);
return (
<Card withBorder>
<Card p="xs" withBorder>
<Grid>
<Grid.Col className={classes.alignSelfCenter} xs={12} md={6}>
<Group spacing="sm">
<ThemeIcon color="green" variant="light">
<ThemeIcon color={secretIsPresent ? 'green' : 'red'} variant="light" size="lg">
<Icon size={18} />
</ThemeIcon>
<Stack spacing={0}>
<Title className={classes.subtitle} order={6}>
{t(label)}
</Title>
<Group spacing="xs">
<Title className={classes.subtitle} order={6}>
{t(label)}
</Title>
<Group spacing="xs">
{secretIsPresent ? (
<Badge className={classes.textTransformUnset} color="green" variant="dot">
{t('integration.type.defined')}
</Badge>
) : (
<Badge className={classes.textTransformUnset} color="red" variant="dot">
{t('integration.type.undefined')}
</Badge>
)}
{type === 'private' ? (
<Tooltip
label={t('integration.type.explanationPrivate')}
width={200}
multiline
withinPortal
withArrow
>
<Badge className={classes.textTransformUnset} color="orange" variant="dot">
{t('integration.type.private')}
</Badge>
</Tooltip>
) : (
<Tooltip
label={t('integration.type.explanationPublic')}
width={200}
multiline
withinPortal
withArrow
>
<Badge className={classes.textTransformUnset} color="red" variant="dot">
{t('integration.type.public')}
</Badge>
</Tooltip>
)}
</Group>
</Group>
<Text size="xs" color="dimmed">
{type === 'private'
? 'Private: Once saved, you cannot read out this value again'
: 'Public: Can be read out repeatedly'}
</Text>
</Stack>
</Group>
</Grid.Col>
@@ -80,4 +132,7 @@ const useStyles = createStyles(() => ({
alignSelfCenter: {
alignSelf: 'center',
},
textTransformUnset: {
textTransform: 'inherit',
},
}));

View File

@@ -36,7 +36,7 @@ export const IntegrationSelector = ({ form }: IntegrationSelectorProps) => {
label: 'Transmission',
},
{
value: 'qbittorrent',
value: 'qBittorrent',
image: 'https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/qbittorrent.png',
label: 'qBittorrent',
},
@@ -100,16 +100,20 @@ export const IntegrationSelector = ({ form }: IntegrationSelectorProps) => {
placeholder={t('integration.type.placeholder')}
itemComponent={SelectItemComponent}
data={data}
maxDropdownHeight={150}
maxDropdownHeight={250}
dropdownPosition="bottom"
clearable
variant="default"
searchable
filter={(value, item) =>
item.label?.toLowerCase().includes(value.toLowerCase().trim()) ||
item.description?.toLowerCase().includes(value.toLowerCase().trim())
}
icon={
form.values.integration?.type && (
<img
src={data.find((x) => x.value === form.values.integration?.type)?.image}
alt="test"
alt="integration"
width={20}
height={20}
/>
@@ -119,6 +123,7 @@ export const IntegrationSelector = ({ form }: IntegrationSelectorProps) => {
form.setFieldValue('integration.properties', getNewProperties(value));
inputProps.onChange(value);
}}
withinPortal
{...inputProps}
/>
);
@@ -126,17 +131,23 @@ export const IntegrationSelector = ({ form }: IntegrationSelectorProps) => {
interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
image: string;
description: string;
label: string;
}
const SelectItemComponent = forwardRef<HTMLDivElement, ItemProps>(
({ image, label, ...others }: ItemProps, ref) => (
({ image, label, description, ...others }: ItemProps, ref) => (
<div ref={ref} {...others}>
<Group noWrap>
<img src={image} alt="integration icon" width={20} height={20} />
<div>
<Text size="sm">{label}</Text>
{description && (
<Text size="xs" color="dimmed">
{description}
</Text>
)}
</div>
</Group>
</div>

View File

@@ -45,6 +45,7 @@ export const IntegrationOptionsRenderer = ({ form }: IntegrationOptionsRendererP
const formValue = form.values.integration?.properties[indexInFormValue];
const isPresent = formValue?.isDefined;
const accessabilityType = formValue?.type;
if (!definition) {
return (
@@ -57,6 +58,7 @@ export const IntegrationOptionsRenderer = ({ form }: IntegrationOptionsRendererP
secretIsPresent={isPresent}
setIcon={IconKey}
value={formValue.value}
type={accessabilityType}
{...form.getInputProps(`integration.properties.${index}.value`)}
/>
);
@@ -72,6 +74,7 @@ export const IntegrationOptionsRenderer = ({ form }: IntegrationOptionsRendererP
value=""
secretIsPresent={isPresent}
setIcon={definition.icon}
type={accessabilityType}
{...form.getInputProps(`integration.properties.${index}.value`)}
/>
);

View File

@@ -97,8 +97,8 @@ export const AvailableElementTypes = ({
iconUrl: '/imgs/logo/logo.png',
},
network: {
enabledStatusChecker: false,
okStatus: [],
enabledStatusChecker: true,
okStatus: [200],
},
behaviour: {
isOpeningNewTab: true,

View File

@@ -1,5 +1,6 @@
import { useModals } from '@mantine/modals';
import { TablerIcon } from '@tabler/icons';
import { showNotification } from '@mantine/notifications';
import { IconChecks, TablerIcon } from '@tabler/icons';
import { useTranslation } from 'next-i18next';
import { useConfigContext } from '../../../../../../config/provider';
import { useConfigStore } from '../../../../../../config/store';
@@ -83,8 +84,13 @@ export const WidgetElementType = ({ id, image, disabled, widget }: WidgetElement
true,
!isEditMode
);
closeModal('selectElement');
showNotification({
title: t('descriptor.name'),
message: t('descriptor.description'),
icon: <IconChecks stroke={1.5} />,
color: 'teal',
});
};
return (