Merge pull request #366 from vlaminck/every-element-update

Updated the every element app to better represent what each element can and can't do
This commit is contained in:
Steve Vlaminck
2015-12-14 13:57:02 -06:00

View File

@@ -1,7 +1,7 @@
/** /**
* Every Element * Every Element
* *
* Copyright 2014 SmartThings * Copyright 2015 SmartThings
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at: * in compliance with the License. You may obtain a copy of the License at:
@@ -14,349 +14,555 @@
* *
*/ */
definition( definition(
name: "Every Element", name: "Every Element",
namespace: "smartthings/examples", namespace: "smartthings/examples",
author: "SmartThings", author: "SmartThings",
description: "Every element demonstration app", description: "Every element demonstration app",
category: "SmartThings Internal", category: "SmartThings Internal",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png" iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png"
) )
preferences { preferences {
page(name: "firstPage") // landing page
page(name: "inputPage") page(name: "firstPage")
page(name: "appPage")
page(name: "labelPage") // PageKit
page(name: "modePage") page(name: "buttonsPage")
page(name: "paragraphPage") page(name: "imagePage")
page(name: "iconPage") page(name: "inputPage")
page(name: "hrefPage") page(name: "inputBooleanPage")
page(name: "buttonsPage") page(name: "inputIconPage")
page(name: "imagePage") page(name: "inputImagePage")
page(name: "videoPage") page(name: "inputDevicePage")
page(name: "deadEnd", title: "Nothing to see here, move along.", content: "foo") page(name: "inputCapabilityPage")
page(name: "flattenedPage") page(name: "inputRoomPage")
page(name: "inputModePage")
page(name: "inputSelectionPage")
page(name: "inputHubPage")
page(name: "inputContactBookPage")
page(name: "inputTextPage")
page(name: "inputTimePage")
page(name: "appPage")
page(name: "hrefPage")
page(name: "paragraphPage")
page(name: "videoPage")
page(name: "labelPage")
page(name: "modePage")
// Every element helper pages
page(name: "deadEnd", title: "Nothing to see here, move along.", content: "foo")
page(name: "flattenedPage")
} }
def firstPage() { def firstPage() {
dynamicPage(name: "firstPage", title: "Where to first?", install: true, uninstall: true) { dynamicPage(name: "firstPage", title: "Where to first?", install: true, uninstall: true) {
section() { section {
href(page: "inputPage", title: "Element: 'input'") href(page: "appPage", title: "Element: 'app'")
href(page: "appPage", title: "Element: 'app'") href(page: "buttonsPage", title: "Element: 'buttons'")
href(page: "labelPage", title: "Element: 'label'") href(page: "hrefPage", title: "Element: 'href'")
href(page: "modePage", title: "Element: 'mode'") href(page: "imagePage", title: "Element: 'image'")
href(page: "paragraphPage", title: "Element: 'paragraph'") href(page: "inputPage", title: "Element: 'input'")
href(page: "iconPage", title: "Element: 'icon'") href(page: "labelPage", title: "Element: 'label'")
href(page: "hrefPage", title: "Element: 'href'") href(page: "modePage", title: "Element: 'mode'")
href(page: "buttonsPage", title: "Element: 'buttons'") href(page: "paragraphPage", title: "Element: 'paragraph'")
href(page: "imagePage", title: "Element: 'image'") href(page: "videoPage", title: "Element: 'video'")
href(page: "videoPage", title: "Element: 'video'") }
} section {
section() { href(page: "flattenedPage", title: "All of the above elements on a single page")
href(page: "flattenedPage", title: "All of the above elements on a single page") }
} }
}
} }
def inputPage() { def inputPage() {
dynamicPage(name: "inputPage", title: "Every 'input' type") { dynamicPage(name: "inputPage", title: "Links to every 'input' element") {
section("enum") { section {
input(type: "enum", name: "enumRefresh", title: "submitOnChange:true", required: false, multiple: true, options: ["one", "two", "three"], submitOnChange: true) href(page: "inputBooleanPage", title: "to boolean page")
if (enumRefresh) { href(page: "inputIconPage", title: "to icon page")
paragraph "${enumRefresh}" href(page: "inputImagePage", title: "to image page")
} href(page: "inputSelectionPage", title: "to selection page")
input(type: "enum", name: "enumSegmented", title: "style:segmented", required: false, multiple: true, options: ["one", "two", "three"], style: "segmented") href(page: "inputTextPage", title: "to text page")
input(type: "enum", name: "enum", title: "required:false, multiple:false", required: false, multiple: false, options: ["one", "two", "three"]) href(page: "inputTimePage", title: "to time page")
input(type: "enum", name: "enumRequired", title: "required:true", required: true, multiple: false, options: ["one", "two", "three"]) }
input(type: "enum", name: "enumMultiple", title: "multiple:true", required: false, multiple: true, options: ["one", "two", "three"]) section("subsets of selection input") {
input(type: "enum", name: "enumWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, options: ["one", "two", "three"], image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") href(page: "inputDevicePage", title: "to device selection page")
input(type: "enum", name: "enumWithGroupedOptions", title: "groupedOptions", description: "This enum has grouped options", required: false, multiple: true, groupedOptions: [ href(page: "inputCapabilityPage", title: "to capability selection page")
[ href(page: "inputRoomPage", title: "to room selection page")
title : "the group title that is displayed", href(page: "inputModePage", title: "to mode selection page")
order : 0, // the order of the group; 0-based href(page: "inputHubPage", title: "to hub selection page")
image : "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", // not yet supported href(page: "inputContactBookPage", title: "to contact-book selection page")
values: [ }
[ }
key : "the value that will be placed in SmartApp settings.", // such as a device id }
value: "the title of the selectable option that is displayed", // such as a device name
order: 0 // the order of the option def inputBooleanPage() {
] dynamicPage(name: "inputBooleanPage") {
] section {
], paragraph "The `required` and `multiple` attributes have no effect because the value will always be either `true` or `false`"
[ }
title : "the second group title that is displayed", section {
order : 1, // the order of the group; 0-based input(type: "boolean", name: "booleanWithoutDescription", title: "without description", description: null)
image : null, // not yet supported input(type: "boolean", name: "booleanWithDescription", title: "with description", description: "This has a description")
values: [ }
[ section("defaultValue: 'true'") {
key : "some_device_id", input(type: "boolean", name: "booleanWithDefaultValue", title: "", description: "", defaultValue: "true")
value: "some_device_name", }
order: 1 // the order of the option. This option will appear second in the list even though it is the first option defined in this map section("with image") {
], input(type: "boolean", name: "booleanWithoutDescriptionWithImage", title: "without description", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", description: null)
[ input(type: "boolean", name: "booleanWithDescriptionWithImage", title: "with description", description: "This has a description", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
key : "some_other_device_id", }
value: "some_other_device_name", }
order: 0 // the order of the option. This option will appear first in the list even though it is not the first option defined in this map }
] def inputIconPage() {
] dynamicPage(name: "inputIconPage") {
] section {
]) paragraph "`description` is not displayed for icon elements"
} paragraph "`multiple` has no effect because you can only choose a single icon"
section("text") { }
input(type: "text", name: "text", title: "required:false, multiple:false", required: false, multiple: false) section("required: true") {
input(type: "text", name: "textRequired", title: "required:true", required: true, multiple: false) input(type: "icon", name: "iconRequired", title: "without description", required: true)
input(type: "text", name: "textWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") input(type: "icon", name: "iconRequiredWithDescription", title: "with description", description: "this is a description", required: true)
} }
section("number") { section("with image") {
input(type: "number", name: "number", title: "required:false, multiple:false", required: false, multiple: false) paragraph "The image specified will be replaced after an icon is selected"
input(type: "number", name: "numberRequired", title: "required:true", required: true, multiple: false) input(type: "icon", name: "iconwithImage", title: "without description", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
input(type: "number", name: "numberWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") }
} }
section("boolean") { }
input(type: "boolean", name: "boolean", title: "required:false, multiple:false", required: false, multiple: false) def inputImagePage() {
input(type: "boolean", name: "booleanWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") dynamicPage(name: "inputImagePage") {
} section {
section("password") { paragraph "This only exists in DeviceTypes. Someone should do something about that. (glares at MikeDave)"
input(type: "password", name: "password", title: "required:false, multiple:false", required: false, multiple: false) paragraph "Go to the device preferences of a Mobile Presence device to see it in action"
input(type: "password", name: "passwordRequired", title: "required:true", required: true, multiple: false) paragraph "If you try to set the value of this, it will not behave as it would in Device Preferences"
input(type: "password", name: "passwordWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") input(type: "image", title: "This is kind of what it looks like", required: false)
} }
section("phone") { }
input(type: "phone", name: "phone", title: "required:false, multiple:false", required: false, multiple: false) }
input(type: "phone", name: "phoneRequired", title: "required:true", required: true, multiple: false)
input(type: "phone", name: "phoneWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
} def optionsGroup(List groups, String title) {
section("email") { def group = [values:[], order: groups.size()]
input(type: "email", name: "email", title: "required:false, multiple:false", required: false, multiple: false) group.title = title ?: ""
input(type: "email", name: "emailRequired", title: "required:true", required: true, multiple: false) groups << group
input(type: "email", name: "emailWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") return groups
} }
section("decimal") { def addValues(List groups, String key, String value) {
input(type: "decimal", name: "decimal", title: "required:false, multiple:false", required: false, multiple: false) def lastGroup = groups[-1]
input(type: "decimal", name: "decimalRequired", title: "required:true", required: true, multiple: false) lastGroup["values"] << [
input(type: "decimal", name: "decimalWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") key: key,
} value: value,
section("mode") { order: lastGroup["values"].size()
input(type: "mode", name: "mode", title: "required:false, multiple:false", required: false, multiple: false) ]
input(type: "mode", name: "modeRequired", title: "required:true", required: true, multiple: false) return groups
input(type: "mode", name: "modeMultiple", title: "multiple:true", required: false, multiple: true) }
input(type: "mode", name: "iconWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") def listToMap(List original) {
} original.inject([:]) { result, v ->
section("icon") { result[v] = v
input(type: "icon", name: "icon", title: "required:false, multiple:false", required: false, multiple: false) return result
input(type: "icon", name: "iconRequired", title: "required:true", required: true, multiple: false) }
input(type: "icon", name: "iconWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") }
} def addGroup(List groups, String title, values) {
section("capability") { if (values instanceof List) {
input(type: "capability.switch", name: "capability", title: "required:false, multiple:false", required: false, multiple: false) values = listToMap(values)
input(type: "capability.switch", name: "capabilityRequired", title: "required:true", required: true, multiple: false) }
input(type: "capability.switch", name: "capabilityMultiple", title: "multiple:true", required: false, multiple: true)
input(type: "capability.switch", name: "capabilityWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") values.inject(optionsGroup(groups, title)) { result, k, v ->
} return addValues(result, k, v)
section("hub") { }
input(type: "hub", name: "hub", title: "required:false, multiple:false", required: false, multiple: false) return groups
input(type: "hub", name: "hubRequired", title: "required:true", required: true, multiple: false) }
input(type: "hub", name: "hubMultiple", title: "multiple:true", required: false, multiple: true) def addGroup(values) {
input(type: "hub", name: "hubWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") addGroup([], null, values)
} }
section("device") { /* Example usage of options builder
input(type: "device.switch", name: "device", title: "required:false, multiple:false", required: false, multiple: false)
input(type: "device.switch", name: "deviceRequired", title: "required:true", required: true, multiple: false) // Creating grouped options
input(type: "device.switch", name: "deviceMultiple", title: "multiple:true", required: false, multiple: true) def newGroups = []
input(type: "device.switch", name: "deviceWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") addGroup(newGroups, "first group", ["foo", "bar", "baz"])
} addGroup(newGroups, "second group", [zero: "zero", one: "uno", two: "dos", three: "tres"])
section("time") {
input(type: "time", name: "time", title: "required:false, multiple:false", required: false, multiple: false) // simple list
input(type: "time", name: "timeRequired", title: "required:true", required: true, multiple: false) addGroup(["a", "b", "c"])
input(type: "time", name: "timeWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
} // simple map
section("contact-book") { addGroup(["a": "yes", "b": "no", "c": "maybe"])
input("recipients", "contact", title: "Notify", description: "Send notifications to") { */
input(type: "phone", name: "phone", title: "Send text message to", required: false, multiple: false)
input(type: "boolean", name: "boolean", title: "Send push notification", required: false, multiple: false)
} def inputSelectionPage() {
}
} def englishOptions = ["One", "Two", "Three"]
def spanishOptions = ["Uno", "Dos", "Tres"]
def groupedOptions = []
addGroup(groupedOptions, "English", englishOptions)
addGroup(groupedOptions, "Spanish", spanishOptions)
dynamicPage(name: "inputSelectionPage") {
section("options variations") {
paragraph "tap these elements and look at the differences when selecting an option"
input(type: "enum", name: "selectionSimple", title: "Simple options", description: "no separators in the selectable options", groupedOptions: addGroup(englishOptions + spanishOptions))
input(type: "enum", name: "selectionGrouped", title: "Grouped options", description: "separate groups of options with headers", groupedOptions: groupedOptions)
}
section("list vs map") {
paragraph "These should be identical in UI, but are different in code and will produce different settings"
input(type: "enum", name: "selectionList", title: "Choose a device", description: "settings will be something like ['Device1 Label']", groupedOptions: addGroup(["Device1 Label", "Device2 Label"]))
input(type: "enum", name: "selectionMap", title: "Choose a device", description: "settings will be something like ['device1-id']", groupedOptions: addGroup(["device1-id": "Device1 Label", "device2-id": "Device2 Label"]))
}
section("segmented") {
paragraph "segmented should only work if there are either 2 or 3 options to choose from"
input(type: "enum", name: "selectionSegmented1", style: "segmented", title: "1 option", groupedOptions: addGroup(["One"]))
input(type: "enum", name: "selectionSegmented4", style: "segmented", title: "4 options", groupedOptions: addGroup(["One", "Two", "Three", "Four"]))
paragraph "multiple and required will have no effect on segmented selection elements. There will always be exactly 1 option selected"
input(type: "enum", name: "selectionSegmented2", style: "segmented", title: "2 options", options: ["One", "Two"])
input(type: "enum", name: "selectionSegmented3", style: "segmented", title: "3 options", options: ["One", "Two", "Three"])
paragraph "specifying defaultValue still works with segmented selection elements"
input(type: "enum", name: "selectionSegmentedWithDefault", title: "defaulted to 'two'", groupedOptions: addGroup(["One", "Two", "Three"]), defaultValue: "Two")
}
section("required: true") {
input(type: "enum", name: "selectionRequired", title: "This is required", description: "It should look different when nothing is selected", groupedOptions: addGroup(["only option"]), required: true)
}
section("multiple: true") {
input(type: "enum", name: "selectionMultiple", title: "This allows multiple selections", description: "It should look different when nothing is selected", groupedOptions: addGroup(["an option", "another option", "no way, one more?"]), multiple: true)
}
section("with image") {
input(type: "enum", name: "selectionWithImage", title: "This has an image", description: "and a description", groupedOptions: addGroup(["an option", "another option", "no way, one more?"]), image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
}
def inputTextPage() {
dynamicPage(name: "inputTextPage", title: "Every 'text' variation") {
section("style and functional differences") {
input(type: "text", name: "textRequired", title: "required: true", description: "This should look different when nothing has been entered", required: true)
input(type: "text", name: "textWithImage", title: "with image", description: "This should look different when nothing has been entered", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", required: false)
}
section("text") {
input(type: "text", name: "text", title: "This has an alpha-numeric keyboard", description: "no special formatting", required: false)
}
section("password") {
input(type: "password", name: "password", title: "This has an alpha-numeric keyboard", description: "masks value", required: false)
}
section("email") {
input(type: "email", name: "email", title: "This has an email-specific keyboard", description: "no special formatting", required: false)
}
section("phone") {
input(type: "phone", name: "phone", title: "This has a numeric keyboard", description: "formatted for phone numbers", required: false)
}
section("decimal") {
input(type: "decimal", name: "decimal", title: "This has an numeric keyboard with decimal point", description: "no special formatting", required: false)
}
section("number") {
input(type: "number", name: "number", title: "This has an numeric keyboard without decimal point", description: "no special formatting", required: false)
}
section("specified ranges") {
paragraph "You can limit number and decimal inputs to a specific range."
input(range: "50..150", type: "decimal", name: "decimalRange50..150", title: "only values between 50 and 150 will pass validation", description: "no special formatting", required: false)
paragraph "Negative limits will add a negative symbol to the keyboard."
input(range: "-50..50", type: "number", name: "numberRange-50..50", title: "only values between -50 and 50 will pass validation", description: "no special formatting", required: false)
paragraph "Specify * to not limit one side or the other."
input(range: "*..0", type: "decimal", name: "decimalRange*..0", title: "only negative values will pass validation", description: "no special formatting", required: false)
input(range: "*..*", type: "number", name: "numberRange*..*", title: "only positive values will pass validation", description: "no special formatting", required: false)
paragraph "If you don't specify a range, it defaults to 0..*"
}
}
}
def inputTimePage() {
dynamicPage(name: "inputTimePage") {
section {
input(type: "time", name: "timeWithDescription", title: "a time picker", description: "with a description", required: false)
input(type: "time", name: "timeWithoutDescription", title: "without a description", description: null, required: false)
input(type: "time", name: "timeRequired", title: "required: true", required: true)
}
}
}
/// selection subsets
def inputDevicePage() {
dynamicPage(name: "inputDevicePage") {
section("required: true") {
input(type: "device.switch", name: "deviceRequired", title: "This is required", description: "It should look different when nothing is selected")
}
section("multiple: true") {
input(type: "device.switch", name: "deviceMultiple", title: "This is required", description: "It should look different when nothing is selected", multiple: true)
}
section("with image") {
input(type: "device.switch", name: "deviceRequired", title: "This has an image", description: "and a description", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
}
def inputCapabilityPage() {
dynamicPage(name: "inputCapabilityPage") {
section("required: true") {
input(type: "capability.switch", name: "capabilityRequired", title: "This is required", description: "It should look different when nothing is selected")
}
section("multiple: true") {
input(type: "capability.switch", name: "capabilityMultiple", title: "This is required", description: "It should look different when nothing is selected", multiple: true)
}
section("with image") {
input(type: "capability.switch", name: "capabilityRequired", title: "This has an image", description: "and a description", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
}
def inputRoomPage() {
dynamicPage(name: "inputRoomPage") {
section("required: true") {
input(type: "room", name: "roomRequired", title: "This is required", description: "It should look different when nothing is selected")
}
section("multiple: true") {
input(type: "room", name: "roomMultiple", title: "This is required", description: "It should look different when nothing is selected", multiple: true)
}
section("with image") {
input(type: "room", name: "roomRequired", title: "This has an image", description: "and a description", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
}
def inputModePage() {
dynamicPage(name: "inputModePage") {
section("required: true") {
input(type: "mode", name: "modeRequired", title: "This is required", description: "It should look different when nothing is selected")
}
section("multiple: true") {
input(type: "mode", name: "modeMultiple", title: "This is required", description: "It should look different when nothing is selected", multiple: true)
}
section("with image") {
input(type: "mode", name: "modeRequired", title: "This has an image", description: "and a description", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
}
def inputHubPage() {
dynamicPage(name: "inputHubPage") {
section("required: true") {
input(type: "hub", name: "hubRequired", title: "This is required", description: "It should look different when nothing is selected")
}
section("multiple: true") {
input(type: "hub", name: "hubMultiple", title: "This is required", description: "It should look different when nothing is selected", multiple: true)
}
section("with image") {
input(type: "hub", name: "hubRequired", title: "This has an image", description: "and a description", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
}
def inputContactBookPage() {
dynamicPage(name: "inputContactBookPage") {
section("required: true") {
input(type: "contact", name: "contactRequired", title: "This is required", description: "It should look different when nothing is selected")
}
section("multiple: true") {
input(type: "contact", name: "contactMultiple", title: "This is required", description: "It should look different when nothing is selected", multiple: true)
}
section("with image") {
input(type: "contact", name: "contactRequired", title: "This has an image", description: "and a description", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
} }
def appPage() { def appPage() {
dynamicPage(name: "appPage", title: "Every 'app' type") { dynamicPage(name: "appPage", title: "Every 'app' type") {
section { section {
paragraph "These won't work unless you create a child SmartApp to link to... Sorry." paragraph "These won't work unless you create a child SmartApp to link to... Sorry."
} }
section("app") { section("app") {
app( app(
name: "app", name: "app",
title: "required:false, multiple:false", title: "required:false, multiple:false",
required: false, required: false,
multiple: false, multiple: false,
namespace: "Steve", namespace: "Steve",
appName: "Child SmartApp" appName: "Child SmartApp"
) )
app(name: "appRequired", title: "required:true", required: true, multiple: false, namespace: "Steve", appName: "Child SmartApp") app(name: "appRequired", title: "required:true", required: true, multiple: false, namespace: "Steve", appName: "Child SmartApp")
app(name: "appComplete", title: "state:complete", required: false, multiple: false, namespace: "Steve", appName: "Child SmartApp", state: "complete") app(name: "appComplete", title: "state:complete", required: false, multiple: false, namespace: "Steve", appName: "Child SmartApp", state: "complete")
app(name: "appWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", namespace: "Steve", appName: "Child SmartApp") app(name: "appWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", namespace: "Steve", appName: "Child SmartApp")
} }
section("multiple:true") { section("multiple:true") {
app(name: "appMultiple", title: "multiple:true", required: false, multiple: true, namespace: "Steve", appName: "Child SmartApp") app(name: "appMultiple", title: "multiple:true", required: false, multiple: true, namespace: "Steve", appName: "Child SmartApp")
} }
section("multiple:true with image") { section("multiple:true with image") {
app(name: "appMultipleWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", namespace: "Steve", appName: "Child SmartApp") app(name: "appMultipleWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", namespace: "Steve", appName: "Child SmartApp")
} }
} }
} }
def labelPage() { def labelPage() {
dynamicPage(name: "labelPage", title: "Every 'Label' type") { dynamicPage(name: "labelPage", title: "Every 'Label' type") {
section("label") { section("label") {
label(name: "label", title: "required:false, multiple:false", required: false, multiple: false) paragraph "The difference between a label element and a text input element is that the label element will effect the SmartApp directly by setting the label. An input element will place the set value in the SmartApp's settings."
label(name: "labelRequired", title: "required:true", required: true, multiple: false) paragraph "There are 3 here as an example. Never use more than 1 label element on a page."
label(name: "labelWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") label(name: "label", title: "required:false, multiple:false", required: false, multiple: false)
} label(name: "labelRequired", title: "required:true", required: true, multiple: false)
} label(name: "labelWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
} }
def modePage() { def modePage() {
dynamicPage(name: "modePage", title: "Every 'mode' type") { // TODO: finish this dynamicPage(name: "modePage", title: "Every 'mode' type") { // TODO: finish this
section("mode") { section("mode") {
mode(name: "mode", title: "required:false, multiple:false", required: false, multiple: false) paragraph "The difference between a mode element and a mode input element is that the mode element will effect the SmartApp directly by setting the modes it executes in. A mode input element will place the set value in the SmartApp's settings."
mode(name: "modeRequired", title: "required:true", required: true, multiple: false) paragraph "Another difference is that you can select 'All Modes' when choosing which mode the SmartApp should execute in. This is the same as selecting no modes. When a SmartApp does not have modes specified, it will execute in all modes."
mode(name: "modeMultiple", title: "multiple:true", required: false, multiple: true) paragraph "There are 4 here as an example. Never use more than 1 mode element on a page."
mode(name: "modeWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") mode(name: "mode", title: "required:false, multiple:false", required: false, multiple: false)
} mode(name: "modeRequired", title: "required:true", required: true, multiple: false)
} mode(name: "modeMultiple", title: "multiple:true", required: false, multiple: true)
mode(name: "modeWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, multiple: true, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
} }
def paragraphPage() { def paragraphPage() {
dynamicPage(name: "paragraphPage", title: "Every 'paragraph' type") { dynamicPage(name: "paragraphPage", title: "Every 'paragraph' type") {
section("paragraph") { section("paragraph") {
paragraph "This us how you should make a paragraph element" paragraph "This is how you should make a paragraph element"
paragraph image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", "This is a long description, blah, blah, blah." paragraph image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", "This is a long description, blah, blah, blah."
} }
} }
}
def iconPage() {
dynamicPage(name: "iconPage", title: "Every 'icon' type") { // TODO: finish this
section("icon") {
icon(name: "icon", title: "required:false, multiple:false", required: false, multiple: false)
icon(name: "iconRequired", title: "required:true", required: true, multiple: false)
icon(name: "iconWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
}
}
} }
def hrefPage() { def hrefPage() {
dynamicPage(name: "hrefPage", title: "Every 'href' type") { dynamicPage(name: "hrefPage", title: "Every 'href' variation") {
section("page") { section("stylistic differences") {
href(name: "hrefPage", title: "required:false, multiple:false", required: false, multiple: false, page: "deadEnd") href(page: "deadEnd", title: "state: 'complete'", description: "gives the appearance of an input that has been filled out", state: "complete")
href(name: "hrefPageRequired", title: "required:true", required: true, multiple: false, page: "deadEnd", description: "Don't make hrefs required") href(page: "deadEnd", title: "with image", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png")
href(name: "hrefPageComplete", title: "state:complete", required: false, multiple: false, page: "deadEnd", state: "complete") href(page: "deadEnd", title: "with image and description", description: "and state: 'complete'", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", state: "complete")
href(name: "hrefPageWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", page: "deadEnd",) }
} section("functional differences") {
section("external") { href(page: "deadEnd", title: "to a page within the app")
href(name: "hrefExternal", title: "required:false, multiple:false", required: false, multiple: false, style: "external", url: "http://smartthings.com/") href(url: "http://www.google.com", title: "to a url using all defaults")
href(name: "hrefExternalRequired", title: "required:true", required: true, multiple: false, style: "external", url: "http://smartthings.com/", description: "Don't make hrefs required") href(url: "http://www.google.com", title: "external: true", description: "takes you outside the app", external: true)
href(name: "hrefExternalComplete", title: "state:complete", required: false, multiple: true, style: "external", url: "http://smartthings.com/", state: "complete") }
href(name: "hrefExternalWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", url: "http://smartthings.com/") }
}
section("embedded") {
href(name: "hrefEmbedded", title: "required:false, multiple:false", required: false, multiple: false, style: "embedded", url: "http://smartthings.com/")
href(name: "hrefEmbeddedRequired", title: "required:true", required: true, multiple: false, style: "embedded", url: "http://smartthings.com/", description: "Don't make hrefs required")
href(name: "hrefEmbeddedComplete", title: "state:complete", required: false, multiple: true, style: "embedded", url: "http://smartthings.com/", state: "complete")
href(name: "hrefEmbeddedWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", url: "http://smartthings.com/")
}
}
} }
def buttonsPage() { def buttonsPage() {
dynamicPage(name: "buttonsPage", title: "Every 'button' type") { dynamicPage(name: "buttonsPage", title: "Every 'button' type") {
section("buttons") { section("Simple Buttons") {
buttons(name: "buttons", title: "required:false, multiple:false", required: false, multiple: false, buttons: [ paragraph "If there are an odd number of buttons, the last button will span the entire view area."
[label: "foo", action: "foo"], buttons(name: "buttons1", title: "1 button", buttons: [
[label: "bar", action: "bar"] [label: "foo", action: "foo"]
]) ])
buttons(name: "buttonsRequired", title: "required:true", required: true, multiple: false, buttons: [ buttons(name: "buttons2", title: "2 buttons", buttons: [
[label: "foo", action: "foo"], [label: "foo", action: "foo"],
[label: "bar", action: "bar"] [label: "bar", action: "bar"]
]) ])
buttons(name: "buttonsWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", buttons: [ buttons(name: "buttons3", title: "3 buttons", buttons: [
[label: "foo", action: "foo"], [label: "foo", action: "foo"],
[label: "bar", action: "bar"] [label: "bar", action: "bar"],
]) [label: "baz", action: "baz"]
} ])
section("Colored Buttons") { buttons(name: "buttonsWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", buttons: [
buttons(name: "buttonsColoredSpecial", title: "special strings", description: "SmartThings highly recommends using these colors", buttons: [ [label: "foo", action: "foo"],
[label: "complete", action: "bar", backgroundColor: "complete"], [label: "bar", action: "bar"]
[label: "required", action: "bar", backgroundColor: "required"] ])
]) }
buttons(name: "buttonsColoredHex", title: "hex values work", buttons: [ section("Colored Buttons") {
[label: "bg: #000dff", action: "foo", backgroundColor: "#000dff"], buttons(name: "buttonsColoredSpecial", title: "special strings", description: "SmartThings highly recommends using these colors", buttons: [
[label: "fg: #ffac00", action: "foo", color: "#ffac00"], [label: "complete", action: "bar", backgroundColor: "complete"],
[label: "both fg and bg", action: "foo", color: "#ffac00", backgroundColor: "#000dff"] [label: "required", action: "bar", backgroundColor: "required"]
]) ])
buttons(name: "buttonsColoredString", title: "strings work too", buttons: [ buttons(name: "buttonsColoredHex", title: "hex values work", buttons: [
[label: "green", action: "foo", backgroundColor: "green"], [label: "bg: #000dff", action: "foo", backgroundColor: "#000dff"],
[label: "red", action: "foo", backgroundColor: "red"], [label: "fg: #ffac00", action: "foo", color: "#ffac00"],
[label: "both fg and bg", action: "foo", color: "red", backgroundColor: "green"] [label: "both fg and bg", action: "foo", color: "#ffac00", backgroundColor: "#000dff"]
]) ])
} buttons(name: "buttonsColoredString", title: "strings work too", buttons: [
} [label: "green", action: "foo", backgroundColor: "green"],
[label: "red", action: "foo", backgroundColor: "red"],
[label: "both fg and bg", action: "foo", color: "red", backgroundColor: "green"]
])
}
}
} }
def imagePage() { def imagePage() {
dynamicPage(name: "imagePage", title: "Every 'image' type") { // TODO: finish thise dynamicPage(name: "imagePage", title: "Every 'image' type") { // TODO: finish thise
section("image") { section("image") {
image "http://f.cl.ly/items/1k1S0A0m3805402o3O12/20130915-191127.jpg" image "http://f.cl.ly/items/1k1S0A0m3805402o3O12/20130915-191127.jpg"
image(name: "imageWithImage", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, image: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png") image(name: "imageWithMultipleImages", title: "This element has an image and a long title.", description: "I am setting long title and descriptions to test the offset", required: false, images: ["https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", "http://f.cl.ly/items/1k1S0A0m3805402o3O12/20130915-191127.jpg"])
} }
} }
} }
def videoPage() { def videoPage() {
dynamicPage(name: "imagePage", title: "Every 'image' type") { // TODO: finish this dynamicPage(name: "videoPage", title: "Every 'video' type") { // TODO: finish this
section("video") { section("video") {
// TODO: update this when there is a videoElement method // TODO: update this when there is a videoElement method
element(name: "videoElement", element: "video", type: "video", title: "this is a video!", description: "I am setting long title and descriptions to test the offset", required: false, image: "http://ec2-54-161-144-215.compute-1.amazonaws.com:8081/jesse/cam1/54aafcd1c198347511c26321.jpg", video: "http://ec2-54-161-144-215.compute-1.amazonaws.com:8081/jesse/cam1/54aafcd1c198347511c2631f.mp4") element(name: "videoElement", element: "video", type: "video", title: "this is a video!", description: "I am setting long title and descriptions to test the offset", required: false, image: "http://f.cl.ly/items/0w0D1p0K2D0d190F3H3N/Image%202015-12-14%20at%207.57.27%20AM.jpg", video: "http://f.cl.ly/items/3O2L03471l2K3E3l3K1r/Zombie%20Kid%20Likes%20Turtles.mp4")
} }
} }
} }
def flattenedPage() { def flattenedPage() {
def allSections = [] def allSections = []
firstPage().sections.each { section -> firstPage().sections[0].body.each { hrefElement ->
section.body.each { hrefElement -> if (hrefElement.name != "inputPage") {
if (hrefElement.page != "flattenedPage") { // inputPage is a bunch of hrefs
allSections += "${hrefElement.page}"().sections allSections += "${hrefElement.page}"().sections
} }
} }
} // collect the input elements
def flattenedPage = dynamicPage(name: "flattenedPage", title: "All elements in one page!") {} inputPage().sections.each { section ->
flattenedPage.sections = allSections section.body.each { hrefElement ->
return flattenedPage allSections += "${hrefElement.page}"().sections
}
}
def flattenedPage = dynamicPage(name: "flattenedPage", title: "All elements in one page!") {}
flattenedPage.sections = allSections
return flattenedPage
} }
def foo() { def foo() {
dynamicPage(name: "deadEnd") { dynamicPage(name: "deadEnd") {
section { }
} }
} }
def installed() { def installed() {
log.debug "Installed with settings: ${settings}" log.debug "Installed with settings: ${settings}"
initialize() initialize()
} }
def updated() { def updated() {
log.debug "Updated with settings: ${settings}" log.debug "Updated with settings: ${settings}"
unsubscribe() unsubscribe()
initialize() initialize()
} }
def initialize() { def initialize() {
// TODO: subscribe to attributes, devices, locations, etc. // TODO: subscribe to attributes, devices, locations, etc.
} }