Feature: iFrame widget (#2261)

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
pull/2272/head
Reiss Cashmore 1 year ago committed by GitHub
parent 5512d05f00
commit ebd384c62d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,35 @@
---
title: iFrame
Description: Add a custom iFrame Widget
---
A basic iFrame widget to show external content, see the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) for more details about some of the options.
!!! warning
Requests made via the iFrame widget are inherently **not proxied** as they are made from the browser itself.
## Basic Example
```yaml
widget:
type: iframe
name: myIframe
src: http://example.com
```
## Full Example
```yaml
widget:
type: iframe
name: myIframe
src: http://example.com
classes: h-60 sm:h-60 md:h-60 lg:h-60 xl:h-60 2xl:h-72 # optional, use tailwind height classes, see https://tailwindcss.com/docs/height
referrerPolicy: same-origin # optional, no default
allowPolicy: autoplay fullscreen gamepad # optional, no default
allowFullscreen: false # optional, default: true
loadingStrategy: eager # optional, default: eager
allowScrolling: no # optional, default: yes
refreshInterval: 2000 # optional, no default
```

@ -63,6 +63,7 @@ nav:
- widgets/services/healthchecks.md - widgets/services/healthchecks.md
- widgets/services/homeassistant.md - widgets/services/homeassistant.md
- widgets/services/homebridge.md - widgets/services/homebridge.md
- widgets/services/iframe.md
- widgets/services/immich.md - widgets/services/immich.md
- widgets/services/jackett.md - widgets/services/jackett.md
- widgets/services/jdownloader.md - widgets/services/jdownloader.md

@ -366,6 +366,13 @@ export function cleanServiceGroups(groups) {
firstDayInWeek, firstDayInWeek,
view, view,
maxEvents, maxEvents,
src, // iframe widget
classes,
referrerPolicy,
allowPolicy,
allowFullscreen,
loadingStrategy,
allowScrolling,
} = cleanedService.widget; } = cleanedService.widget;
let fieldsList = fields; let fieldsList = fields;
@ -413,6 +420,16 @@ export function cleanServiceGroups(groups) {
if (app) cleanedService.widget.app = app; if (app) cleanedService.widget.app = app;
if (podSelector) cleanedService.widget.podSelector = podSelector; if (podSelector) cleanedService.widget.podSelector = podSelector;
} }
if (type === "iframe") {
if (src) cleanedService.widget.src = src;
if (classes) cleanedService.widget.classes = classes;
if (referrerPolicy) cleanedService.widget.referrerPolicy = referrerPolicy;
if (allowPolicy) cleanedService.widget.allowPolicy = allowPolicy;
if (allowFullscreen) cleanedService.widget.allowFullscreen = allowFullscreen;
if (loadingStrategy) cleanedService.widget.loadingStrategy = loadingStrategy;
if (allowScrolling) cleanedService.widget.allowScrolling = allowScrolling;
if (refreshInterval) cleanedService.widget.refreshInterval = refreshInterval;
}
if (["opnsense", "pfsense"].includes(type)) { if (["opnsense", "pfsense"].includes(type)) {
if (wan) cleanedService.widget.wan = wan; if (wan) cleanedService.widget.wan = wan;
} }

@ -15,6 +15,7 @@ const components = {
channelsdvrserver: dynamic(() => import("./channelsdvrserver/component")), channelsdvrserver: dynamic(() => import("./channelsdvrserver/component")),
cloudflared: dynamic(() => import("./cloudflared/component")), cloudflared: dynamic(() => import("./cloudflared/component")),
coinmarketcap: dynamic(() => import("./coinmarketcap/component")), coinmarketcap: dynamic(() => import("./coinmarketcap/component")),
iframe: dynamic(() => import("./iframe/component")),
customapi: dynamic(() => import("./customapi/component")), customapi: dynamic(() => import("./customapi/component")),
deluge: dynamic(() => import("./deluge/component")), deluge: dynamic(() => import("./deluge/component")),
diskstation: dynamic(() => import("./diskstation/component")), diskstation: dynamic(() => import("./diskstation/component")),

@ -0,0 +1,50 @@
import { useState, useEffect } from "react";
import classNames from "classnames";
import Container from "components/services/widget/container";
export default function Component({ service }) {
const [refreshTimer, setRefreshTimer] = useState(0);
const { widget } = service;
useEffect(() => {
if (widget?.refreshInterval) {
setInterval(
() => setRefreshTimer(refreshTimer + 1),
widget?.refreshInterval < 1000 ? 1000 : widget?.refreshInterval,
);
}
}, [refreshTimer, widget?.refreshInterval]);
const scrollingDisableStyle = widget?.allowScrolling === "no" ? { pointerEvents: "none", overflow: "hidden" } : {};
const classes = widget?.classes || "h-60 sm:h-60 md:h-60 lg:h-60 xl:h-60 2xl:h-72";
return (
<Container service={service}>
<div
className={classNames(
"bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center text-center",
"service-block",
)}
>
<iframe
src={widget?.src}
key={`${widget?.name}-${refreshTimer}`}
name={widget?.name}
title={widget?.name}
allow={widget?.allowPolicy}
allowFullScreen={widget?.allowfullscreen}
referrerPolicy={widget?.referrerPolicy}
loading={widget?.loadingStrategy}
scrolling={widget?.allowScrolling}
style={{
scrollingDisableStyle,
}}
className={`rounded w-full ${classes}`}
/>
</div>
</Container>
);
}

@ -0,0 +1,3 @@
const widget = {};
export default widget;

@ -76,5 +76,9 @@ module.exports = {
"dark:bg-white", "dark:bg-white",
"bg-orange-400", "bg-orange-400",
"dark:bg-orange-400", "dark:bg-orange-400",
{
pattern: /h-([0-96])/,
variants: ["sm", "md", "lg", "xl", "2xl"],
},
], ],
}; };

Loading…
Cancel
Save