diff --git a/public/locales/en/modules/iframe.json b/public/locales/en/modules/iframe.json new file mode 100644 index 000000000..6bfad9ea1 --- /dev/null +++ b/public/locales/en/modules/iframe.json @@ -0,0 +1,23 @@ +{ + "descriptor": { + "name": "IFrame", + "description": "Embed any content from the internet. Some websites may restrict access.", + "settings": { + "title": "IFrame settings", + "embedUrl": { + "label": "Embed URL" + }, + "allowFullScreen": { + "label": "Allow full screen" + } + } + }, + "card": { + "errors": { + "noUrl": { + "title": "Enter an URL", + "text": "Ensure that you've entered a valid address in the configuration of your widget" + } + } + } +} \ No newline at end of file diff --git a/src/tools/server/translation-namespaces.ts b/src/tools/server/translation-namespaces.ts index ec2b9b044..3e819398d 100644 --- a/src/tools/server/translation-namespaces.ts +++ b/src/tools/server/translation-namespaces.ts @@ -29,6 +29,7 @@ export const dashboardNamespaces = [ 'modules/torrents-status', 'modules/weather', 'modules/ping', + 'modules/iframe', 'modules/rss', 'modules/docker', 'modules/dashdot', diff --git a/src/widgets/iframe/IFrameTile.tsx b/src/widgets/iframe/IFrameTile.tsx new file mode 100644 index 000000000..44b17d089 --- /dev/null +++ b/src/widgets/iframe/IFrameTile.tsx @@ -0,0 +1,82 @@ +import { Center, createStyles, Stack, Title, Text, Container } from '@mantine/core'; +import { IconBrowser, IconUnlink } from '@tabler/icons'; +import { useTranslation } from 'next-i18next'; +import { defineWidget } from '../helper'; +import { IWidget } from '../widgets'; + +const definition = defineWidget({ + id: 'iframe', + icon: IconBrowser, + gridstack: { + maxHeight: 12, + maxWidth: 12, + minHeight: 1, + minWidth: 1, + }, + options: { + embedUrl: { + type: 'text', + defaultValue: '', + }, + allowFullScreen: { + type: 'switch', + defaultValue: false, + }, + }, + component: IFrameTile, +}); + +export type IIFrameWidget = IWidget<(typeof definition)['id'], typeof definition>; + +interface IFrameTileProps { + widget: IIFrameWidget; +} + +function IFrameTile({ widget }: IFrameTileProps) { + const { t } = useTranslation('modules/iframe'); + const { classes } = useStyles(); + + if (!widget.properties.embedUrl) { + return ( +
+ + + + + {t('card.errors.noUrl.title')} + + + {t('card.errors.noUrl.text')} + + + +
+ ); + } + + return ( + + + + ); +} + +const useStyles = createStyles(({ radius }) => ({ + iframe: { + borderRadius: radius.sm, + width: '100%', + height: '100%', + border: 'none', + background: 'none', + backgroundColor: 'transparent', + }, +})); + +export default definition; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index c568c2ddf..820795f24 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -2,6 +2,7 @@ import calendar from './calendar/CalendarTile'; import dashdot from './dashDot/DashDotTile'; import date from './date/DateTile'; import torrentNetworkTraffic from './download-speed/TorrentNetworkTrafficTile'; +import iframe from './iframe/IFrameTile'; import mediaServer from './media-server/MediaServerTile'; import rss from './rss/RssWidgetTile'; import torrent from './torrent/TorrentTile'; @@ -19,5 +20,6 @@ export default { date, rss, 'video-stream': videoStream, + iframe, 'media-server': mediaServer, };