diff --git a/public/locales/en/layout/modals/add-app.json b/public/locales/en/layout/modals/add-app.json index 4f40a71cd..6a7670617 100644 --- a/public/locales/en/layout/modals/add-app.json +++ b/public/locales/en/layout/modals/add-app.json @@ -72,6 +72,10 @@ "bottom":"Bottom", "left":"Left" } + }, + "lineClampAppName":{ + "label":"App Name Line Clamp", + "description":"Defines on how many lines your title should fit at it's maximum. Set 0 for unlimited." } }, "integration": { diff --git a/src/components/Dashboard/Modals/EditAppModal/EditAppModal.tsx b/src/components/Dashboard/Modals/EditAppModal/EditAppModal.tsx index 53e713764..34ab62500 100644 --- a/src/components/Dashboard/Modals/EditAppModal/EditAppModal.tsx +++ b/src/components/Dashboard/Modals/EditAppModal/EditAppModal.tsx @@ -205,7 +205,7 @@ export const EditAppModal = ({ setAllowAppNamePropagation(false)} + disallowAppNamePropagation={() => setAllowAppNamePropagation(false)} allowAppNamePropagation={allowAppNamePropagation} /> diff --git a/src/components/Dashboard/Modals/EditAppModal/Tabs/AppereanceTab/AppereanceTab.tsx b/src/components/Dashboard/Modals/EditAppModal/Tabs/AppereanceTab/AppereanceTab.tsx index 14e7e22ac..43a371a0a 100644 --- a/src/components/Dashboard/Modals/EditAppModal/Tabs/AppereanceTab/AppereanceTab.tsx +++ b/src/components/Dashboard/Modals/EditAppModal/Tabs/AppereanceTab/AppereanceTab.tsx @@ -1,4 +1,4 @@ -import { Flex, Select, Stack, Switch, Tabs } from '@mantine/core'; +import { Flex, NumberInput, Select, Stack, Switch, Tabs } from '@mantine/core'; import { UseFormReturnType } from '@mantine/form'; import { useDebouncedValue } from '@mantine/hooks'; import { useTranslation } from 'next-i18next'; @@ -9,13 +9,13 @@ import { IconSelector } from '../../../../../IconSelector/IconSelector'; interface AppearanceTabProps { form: UseFormReturnType AppType>; - disallowAppNameProgagation: () => void; + disallowAppNamePropagation: () => void; allowAppNamePropagation: boolean; } export const AppearanceTab = ({ form, - disallowAppNameProgagation, + disallowAppNamePropagation, allowAppNamePropagation, }: AppearanceTabProps) => { const iconSelectorRef = useRef(); @@ -46,7 +46,7 @@ export const AppearanceTab = ({ defaultValue={form.values.appearance.iconUrl} onChange={(value) => { form.setFieldValue('appearance.iconUrl', value); - disallowAppNameProgagation(); + disallowAppNamePropagation(); }} value={form.values.appearance.iconUrl} ref={iconSelectorRef} @@ -66,26 +66,41 @@ export const AppearanceTab = ({ }} /> {form.values.appearance.appNameStatus === 'normal' && ( - { + form.setFieldValue('appearance.positionAppName', value); + }} + /> + { + form.setFieldValue('appearance.lineClampAppName', value); + }} + /> + )} diff --git a/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx b/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx index 21c8354b1..eb99dbcaa 100644 --- a/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx +++ b/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx @@ -95,6 +95,7 @@ export const AvailableElementTypes = ({ iconUrl: '/imgs/logo/logo.png', appNameStatus: 'normal', positionAppName: 'column', + lineClampAppName: 1, }, network: { enabledStatusChecker: true, diff --git a/src/components/Dashboard/Tiles/Apps/AppPing.tsx b/src/components/Dashboard/Tiles/Apps/AppPing.tsx index b4118c9b3..6aaeda388 100644 --- a/src/components/Dashboard/Tiles/Apps/AppPing.tsx +++ b/src/components/Dashboard/Tiles/Apps/AppPing.tsx @@ -30,7 +30,7 @@ export const AppPing = ({ app }: AppPingProps) => { { const isEditMode = useEditModeStore((x) => x.enabled); - const { cx, classes } = useStyles(); - const { colorScheme } = useMantineTheme(); - const tooltipContent = [ - app.appearance.appNameStatus === "hover" ? app.name : undefined, - app.behaviour.tooltipDescription - ].filter( e => e ).join( ': ' ); + app.appearance.appNameStatus === 'hover' ? app.name : undefined, + app.behaviour.tooltipDescription, + ] + .filter((e) => e) + .join(': '); - const { - classes: { card: cardClass }, - } = useCardStyles(false); + const isRow = app.appearance.positionAppName.includes('row'); function Inner() { return ( - - - - - - + {app.name} + + )} + + ); } return ( - + {!app.url || isEditMode ? ( @@ -110,7 +90,7 @@ export const AppTile = ({ className, app }: AppTileProps) => { component={Link} href={app.behaviour.externalUrl.length > 0 ? app.behaviour.externalUrl : app.url} target={app.behaviour.isOpeningNewTab ? '_blank' : '_self'} - className={cx(classes.button)} + className={`${classes.button} ${classes.base}`} > @@ -121,19 +101,27 @@ export const AppTile = ({ className, app }: AppTileProps) => { }; const useStyles = createStyles((theme, _params, getRef) => ({ - image: { - maxHeight: '90%', - maxWidth: '90%', + base: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + appContent: { + gap: 0, + overflow: 'visible', + flexGrow: 5, }, appName: { wordBreak: 'break-word', }, + appImage: { + flex: '1', + objectFit: 'contain', + overflowY: 'auto', + }, button: { height: '100%', width: '100%', - display: 'flex', - flexDirection: 'column', - alignItems: 'center', gap: 4, }, })); diff --git a/src/modules/Docker/ContainerActionBar.tsx b/src/modules/Docker/ContainerActionBar.tsx index 6dba36c90..7f172297e 100644 --- a/src/modules/Docker/ContainerActionBar.tsx +++ b/src/modules/Docker/ContainerActionBar.tsx @@ -130,7 +130,8 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction appearance: { iconUrl: '/imgs/logo/logo.png', appNameStatus: 'normal', - positionAppName: 'column' + positionAppName: 'column', + lineClampAppName: 1, }, network: { enabledStatusChecker: true, diff --git a/src/tools/config/getFrontendConfig.ts b/src/tools/config/getFrontendConfig.ts index baad9b98b..1266da585 100644 --- a/src/tools/config/getFrontendConfig.ts +++ b/src/tools/config/getFrontendConfig.ts @@ -10,6 +10,8 @@ export const getFrontendConfig = async (name: string): Promise => { let config = getConfig(name); let shouldMigrateConfig = false; + config = migrateAppConfigs(config); + const anyWeatherWidgetWithStringLocation = config.widgets.some( (widget) => widget.type === 'weather' && typeof widget.properties.location === 'string' ); @@ -129,3 +131,18 @@ const migratePiholeIntegrationField = (config: BackendConfigType) => { }), }; }; + +const migrateAppConfigs = (config: BackendConfigType) => { + return { + ...config, + apps: config.apps.map((app) => ({ + ...app, + appearance: { + ...app.appearance, + appNameStatus: app.appearance.appNameStatus?? 'normal', + positionAppName: app.appearance.positionAppName?? 'column', + lineClampAppName: app.appearance.lineClampAppName?? 1, + } + })) + } +} \ No newline at end of file diff --git a/src/types/app.ts b/src/types/app.ts index 7443a863c..adfb8c50a 100644 --- a/src/types/app.ts +++ b/src/types/app.ts @@ -36,6 +36,7 @@ interface AppAppearanceType { iconUrl: string; appNameStatus: "normal"|"hover"|"hidden"; positionAppName: Property.FlexDirection; + lineClampAppName: number; } export type IntegrationType =