Skip to content

Instantly share code, notes, and snippets.

@malesfth
Created November 1, 2020 15:57
Show Gist options
  • Save malesfth/d28133fd021338d1da084bcaf043c8b7 to your computer and use it in GitHub Desktop.
Save malesfth/d28133fd021338d1da084bcaf043c8b7 to your computer and use it in GitHub Desktop.
iOS Scriptable Widget for Grafana
// Parameters:
// {"url":"http://grafana","bearer":"123abc"}
// Optional key in parameters: "theme": system|light|dark|grafana
let grafanaURL = "" //set the URL here for debug
let grafanaBearer = "" // set the API-key here for debug
let wTheme = "system" // set the theme for debug
if (config.runsInWidget) {
const widgetParams = (args.widgetParameter != null ? JSON.parse(args.widgetParameter) : null)
if (widgetParams==null) {
throw new Error("Please long press the widget and add the parameters.")
} else if (!widgetParams.hasOwnProperty("url") && !widgetParams.hasOwnProperty("bearer")) {
throw new Error("Wrong parameters.")
}
grafanaURL = widgetParams.url
grafanaBearer = widgetParams.bearer
if (widgetParams.hasOwnProperty("theme")) {
wTheme = widgetParams.theme
}
}
let wBackground = new LinearGradient()
let wColor = new Color("#ffffff")
let wColorOk = null
let wColorAlert = null
let wColorNeutral = null
setTheme()
let grafanaData = await fetchData()
let wSize = config.widgetFamily || "small" //set size of widget for debug
let widget = await createWidget() || null
if (!config.runsInWidget) {
if (wSize=="large") { await widget.presentLarge() }
else if (wSize=="medium") { await widget.presentMedium() }
else { await widget.presentSmall() }
}
Script.setWidget(widget)
Script.complete()
async function createWidget() {
let w = new ListWidget()
w.backgroundGradient = wBackground
const grafanaOK = (SFSymbol.named("suit.heart.fill")).image
const grafanaAlerting = (SFSymbol.named("heart.slash.fill")).image
const grafanaIMGpaused = (SFSymbol.named("pause")).image
const grafanaIMGnodata = (SFSymbol.named("questionmark")).image
const grafanaIMGpending = (SFSymbol.named("arrowshape.turn.up.right")).image
let content = w.addText("Grafana")
content.font = Font.blackSystemFont(16)
content.textColor = wColor
content.centerAlignText()
if (grafanaData==null) {
w.addSpacer();
content = w.addText("No connection")
content.font = Font.mediumSystemFont(12)
content.textColor = wColor
content.centerAlignText()
w.addSpacer()
return w
}
w.url = grafanaURL
let grafanaIsHealthyStr = "ok"
let grafanaIsHealthy = true
let grafanaHealth = {ok: 0, alerting: 0, paused: 0, pending: 0, no_data: 0}
for(var i = 0; i < grafanaData.length; i++) {
grafanaHealth[grafanaData[i].state] += 1
}
if (grafanaHealth.alerting>0) {
grafanaIsHealthy = false
grafanaIsHealthyStr = "alerting"
}
w.addSpacer(15);
if (wSize=="large") {
let maxRows = 6
let notShown = 0
let wStack = w.addStack()
wStack.centerAlignContent()
wStack.layoutVertically()
wStack.setPadding(5, 20, 0, 20)
for(var i = 0; i < grafanaData.length; i++) {
let gAlert = grafanaData[i]
let layoutStack = null
let rightStack = null
let img = null
let colr = wColorNeutral
switch(gAlert.state) {
case "ok":
img = grafanaOK
colr = wColorOk
break;
case "alerting":
img = grafanaAlerting
colr = wColorAlert
break;
case "paused":
img = grafanaIMGpaused
break;
case "pending":
img = grafanaIMGpending
break;
default:
img = grafanaIMGnodata
break;
}
if(i<maxRows) {
layoutStack = wStack.addStack()
layoutStack.centerAlignContent()
content = layoutStack.addImage(img)
content.imageSize = new Size(28,28)
content.tintColor = colr
layoutStack.addSpacer(15)
content = layoutStack.addText(gAlert.name)
content.font = Font.boldSystemFont(11)
content.textColor = wColor
wStack.addSpacer()
} else if (i==maxRows) {
notShown++
}
}
if (notShown>0) {
layoutStack = w.addStack()
layoutStack.setPadding(20, 0, 0, 20);
content = layoutStack.addText("+"+notShown+" more")
content.font = Font.boldSystemFont(11)
content.textColor = wColor
content.rightAlignText()
}
w.addSpacer()
} else if (wSize=="medium") {
let wStack = w.addStack()
wStack.centerAlignContent()
wStack.setPadding(5, 20, 0, 20);
let layoutStack = wStack.addStack()
layoutStack.centerAlignContent()
content = layoutStack.addImage(grafanaOK)
content.imageSize = new Size(32,32)
content.tintColor = wColorOk
content.centerAlignImage()
layoutStack.addSpacer(12)
content = layoutStack.addText((grafanaHealth.ok).toString())
content.font = Font.mediumSystemFont(16)
content.textColor = wColor
content.centerAlignText()
layoutStack = wStack.addStack()
layoutStack.centerAlignContent()
layoutStack.addSpacer()
content = layoutStack.addImage(grafanaAlerting)
content.imageSize = new Size(32,32)
content.tintColor = wColorAlert
content.centerAlignImage()
layoutStack.addSpacer(12)
content = layoutStack.addText((grafanaHealth.alerting).toString())
content.font = Font.mediumSystemFont(16)
content.textColor = wColor
content.centerAlignText()
layoutStack = wStack.addStack()
layoutStack.centerAlignContent()
layoutStack.addSpacer()
content = layoutStack.addImage(grafanaIMGpaused)
content.imageSize = new Size(32,32)
content.tintColor = wColorNeutral
content.centerAlignImage()
layoutStack.addSpacer(12)
content = layoutStack.addText((grafanaHealth.paused).toString())
content.font = Font.mediumSystemFont(16)
content.textColor = wColor
content.centerAlignText()
wStack = w.addStack()
wStack.centerAlignContent()
wStack.setPadding(20, 0, 0, 20)
layoutStack = wStack.addStack()
layoutStack.centerAlignContent()
layoutStack.addSpacer()
content = layoutStack.addImage(grafanaIMGpending)
content.imageSize = new Size(32,32)
content.tintColor = wColorNeutral
content.centerAlignImage()
layoutStack.addSpacer(12)
content = layoutStack.addText((grafanaHealth.pending).toString())
content.font = Font.mediumSystemFont(16)
content.textColor = wColor
content.centerAlignText()
layoutStack = wStack.addStack()
layoutStack.centerAlignContent()
layoutStack.addSpacer()
content = layoutStack.addImage(grafanaIMGnodata)
content.imageSize = new Size(32,32)
content.tintColor = wColorNeutral
content.centerAlignImage()
layoutStack.addSpacer(12)
content = layoutStack.addText((grafanaHealth.no_data).toString())
content.font = Font.mediumSystemFont(16)
content.textColor = wColor
content.centerAlignText()
layoutStack.addSpacer()
} else {
w.addSpacer()
content = w.addImage((grafanaIsHealthy ? grafanaOK : grafanaAlerting))
content.imageSize = new Size(52,52)
content.tintColor = (grafanaIsHealthy ? wColorOk : wColorAlert)
content.centerAlignImage()
w.addSpacer(5)
content = w.addText(grafanaIsHealthyStr.toUpperCase())
content.font = Font.mediumSystemFont(10)
content.textColor = (grafanaIsHealthy ? wColorOk : wColorAlert)
content.centerAlignText()
w.addSpacer()
}
w.addSpacer()
return w
}
function setTheme() {
wColorOk = Color.green()
wColorAlert = Color.red()
wColorNeutral = Color.gray()
if (wTheme=="system") {
if (Device.isUsingDarkAppearance()) {
wTheme = "dark"
} else {
wTheme = "white"
}
}
wBackground.locations = [0, 1]
if (wTheme=="grafana") {
wBackground.colors = [
Color.red(),
Color.yellow()
]
wColor = new Color("#ffffff")
wColorOk = Color.white()
wColorAlert = Color.white()
wColorNeutral = Color.white()
} else if (wTheme=="dark") {
wBackground.colors = [
new Color("#212121e6"),
new Color("#212121")
]
wColor = new Color("#ffffff")
} else {
wBackground.colors = [
new Color("#ffffffe6"),
new Color("#ffffff")
]
wColor = new Color("#000000")
}
}
async function fetchData() {
try {
let req = new Request(grafanaURL + "/api/alerts/")
req.headers = {"Authorization": "Bearer "+grafanaBearer}
let json = await req.loadJSON()
return json
} catch {
return null
}
}
@Dids
Copy link

Dids commented Nov 17, 2021

Is this still supposed to work on iOS 15.1 and Grafana 8?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment