Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions edge-apps/looker-studio/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/
dist/
*.log
.DS_Store
static/js/*.js
static/js/*.js.map
1 change: 1 addition & 0 deletions edge-apps/looker-studio/.ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
31 changes: 31 additions & 0 deletions edge-apps/looker-studio/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Looker Studio

## Deployment

Create and deploy the Edge App:

```bash
screenly edge-app create --name my-looker-studio --repository
screenly edge-app deploy
screenly edge-app instance create
```

## Configuration

The app accepts the following settings via `screenly.yml`:

- `message` - The message to display on the screen (defaults to "Hello, Mars!")

## Development

```bash
bun install # Install dependencies
bun run build # Build the app
bun test # Run tests
```

## Testing

```bash
bun test
```
394 changes: 394 additions & 0 deletions edge-apps/looker-studio/bun.lock

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions edge-apps/looker-studio/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Looker Studio App</title>
<script src="screenly.js?version=1"></script>
<link rel="stylesheet" href="dist/css/style.css" />
</head>
<body>
<iframe
id="looker-studio-iframe"
title="Looker Studio Dashboard"
src="about:blank"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
></iframe>
<script src="dist/js/main.js"></script>
</body>
</html>
35 changes: 35 additions & 0 deletions edge-apps/looker-studio/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "looker-studio",
"version": "1.0.0",
"devDependencies": {
"@screenly/edge-apps": "workspace:../edge-apps-library",
"@types/bun": "^1.3.6",
"@types/jsdom": "^27.0.0",
"@types/qrcode": "^1.5.6",
"bun-types": "^1.3.6",
"jsdom": "^27.4.0",
"npm-run-all2": "^8.0.4",
"prettier": "^3.8.0",
"typescript": "^5.9.3"
},
"prettier": "../edge-apps-library/.prettierrc.json",
"scripts": {
"prebuild": "bun run type-check",
"generate-mock-data": "screenly edge-app run --generate-mock-data",
"predev": "bun run generate-mock-data && edge-apps-scripts build",
"dev": "run-p build:dev edge-app-server",
"edge-app-server": "screenly edge-app run",
"build": "edge-apps-scripts build",
"build:dev": "edge-apps-scripts build:dev",
"build:prod": "edge-apps-scripts build",
"test": "bun test",
"test:unit": "bun test",
"lint": "edge-apps-scripts lint --fix",
"format": "prettier --write src/ README.md index.html",
"format:check": "prettier --check src/ README.md index.html",
"deploy": "bun run build && screenly edge-app deploy",
"type-check": "edge-apps-scripts type-check",
"prepare": "cd ../edge-apps-library && bun install && bun run build"
},
"type": "module"
}
26 changes: 26 additions & 0 deletions edge-apps/looker-studio/screenly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
syntax: manifest_v1
description: Looker Studio edge app for displaying dashboards
icon: https://playground.srly.io/edge-apps/looker-studio/static/img/icon.svg
author: Screenly, Inc.
ready_signal: true
settings:
embed_url:
type: string
title: Embed URL
optional: false
help_text:
properties:
help_text: Enter the Looker Studio embed URL or paste the full iframe embed code.
type: string
schema_version: 1
refresh_interval:
type: string
default_value: '60'
title: Refresh Interval (seconds)
optional: true
help_text:
properties:
help_text: How often to refresh the dashboard in seconds. Set to 0 to disable auto-refresh.
type: number
schema_version: 1
26 changes: 26 additions & 0 deletions edge-apps/looker-studio/screenly_qc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
syntax: manifest_v1
description: Looker Studio edge app for displaying dashboards
icon: https://playground.srly.io/edge-apps/looker-studio/static/img/icon.svg
author: Screenly, Inc.
ready_signal: true
settings:
embed_url:
type: string
title: Embed URL
optional: false
help_text:
properties:
help_text: "Enter the Looker Studio embed URL or paste the full iframe embed code."
type: string
schema_version: 1
refresh_interval:
type: string
title: Refresh Interval (seconds)
default_value: 60
optional: true
help_text:
properties:
help_text: "How often to refresh the dashboard in seconds. Set to 0 to disable auto-refresh."
type: number
schema_version: 1
19 changes: 19 additions & 0 deletions edge-apps/looker-studio/src/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@import 'tailwindcss';

html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}

#looker-studio-iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
}
67 changes: 67 additions & 0 deletions edge-apps/looker-studio/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import './css/style.css'

import {
setupTheme,
getSettingWithDefault,
signalReady,
} from '@screenly/edge-apps'

function extractUrlFromEmbedSetting(settingValue: string): string | null {
if (settingValue.includes('<iframe')) {
const match = settingValue.match(/<iframe.*?src=["'](.*?)["']/)
if (match && match[1]) {
return match[1]
}
return null
}
return settingValue
}

window.onload = function () {
const embedSettingValue = getSettingWithDefault<string>('embed_url', '')
const refreshInterval = getSettingWithDefault<number>('refresh_interval', 60)
const embedUrl = extractUrlFromEmbedSetting(embedSettingValue)
const iframeElement = document.getElementById(
'looker-studio-iframe',
) as HTMLIFrameElement | null

// Setup branding colors using the library
setupTheme()

if (!iframeElement) {
console.error('Iframe element not found')
signalReady()
return
}

if (!embedUrl) {
console.error('Embed URL not configured or invalid')
signalReady()
return
}

let refreshTimer: number | null = null

const loadIframe = () => {
iframeElement.src = embedUrl
}

const setupRefreshTimer = () => {
if (refreshTimer) {
clearInterval(refreshTimer)
}

if (refreshInterval > 0) {
refreshTimer = window.setInterval(() => {
loadIframe()
}, refreshInterval * 1000)
}
}

iframeElement.onload = () => {
signalReady()
setupRefreshTimer()
}

loadIframe()
}
1 change: 1 addition & 0 deletions edge-apps/looker-studio/static/img/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading