Hi @DrScr3w,
thanks for this nice template.
I made a change to it that makes it easier to adopt the widget to a different number of persons - using the array definition method from Garbage Collection - comma separated lists.
uid: Card_Template_Presence
tags:
- Card Template Presence
- Customizable Template
- ScrewPlate
- Version 1.3
props:
parameters:
- description: "Input without 'px' (Default: none)"
label: Card Height
name: cardHeight
required: false
type: TEXT
groupName: cardGroup
- description: "Input without 'px' (Default: 20px)"
label: Card Border Radius
name: cardBorderRadius
required: false
type: TEXT
groupName: cardGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Card Border Color
name: cardBorderColor
required: false
type: TEXT
groupName: cardGroup
- description: "Input without 'px' (Default: 3px)"
label: Card Border Size
name: cardBorderSize
required: false
type: TEXT
groupName: cardGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Card Background Color
name: cardBgColor
required: false
type: TEXT
groupName: cardGroup
- default: "false"
label: Card Background Image - Show on Card
name: cardBgImageShow
required: false
type: BOOLEAN
groupName: cardGroup
- description: Input file name for Background Image (uploaded to /html/ folder)
label: Card Background Image
name: cardBgImage
required: false
type: TEXT
groupName: cardGroup
- default: "false"
label: Icon - Show on Card
name: iconShow
required: false
type: BOOLEAN
groupName: iconGroup
- description: Use oh:iconName (openHAB icon), f7:iconName (Framework7 icon),
material:iconName (Material icon) or iconify:iconSet:iconName
label: Icon
name: iconName
required: false
type: TEXT
groupName: iconGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Icon Color
name: iconColor
required: false
type: TEXT
groupName: iconGroup
- description: "Input without 'px' (Default: 30px)"
label: Icon Size
name: iconSize
required: false
type: TEXT
groupName: iconGroup
- default: "false"
label: Header - Show on Card
name: headerShow
required: false
type: BOOLEAN
groupName: headerGroup
- description: Input Text to diplay on Header
label: Header
name: headerText
required: false
type: TEXT
groupName: headerGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Header Text Color
name: headerTextColor
required: false
type: TEXT
groupName: headerGroup
- description: "Input without 'px' (Default: 25px)"
label: Header Text Size
name: headerTextSize
required: false
type: TEXT
groupName: headerGroup
- default: "false"
label: Footer - Show on Card
name: footerShow
required: false
type: BOOLEAN
groupName: footerGroup
- description: Input Text to diplay on Footer
label: Footer
name: footerText
required: false
type: TEXT
groupName: footerGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Footer Text Color
name: footerTextColor
required: false
type: TEXT
groupName: footerGroup
- description: "Input without 'px' (Default: 16px)"
label: Footer Text Size
name: footerTextSize
required: false
type: TEXT
groupName: footerGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Content Text Color
name: contentTextColor
required: false
type: TEXT
groupName: contentGroup
- description: "Input without 'px' (Default: 18px)"
label: Content Text Size
name: contentTextSize
required: false
type: TEXT
groupName: contentGroup
- description: "Input without 'px' (Default: 30px)"
label: Content Icon Size
name: contentIconSize
required: false
type: TEXT
groupName: contentGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Content Icon Color
name: contentIconColor
required: false
type: TEXT
groupName: contentGroup
- description: "Input text value for present (Default: present)"
label: Present Text Value
name: presentTextValue
required: false
type: TEXT
groupName: customGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Present Icon Color (only usable if the icon is transparent)
name: presentIconColor
required: false
type: TEXT
groupName: customGroup
- description: "Input text value for absence (Default: absent)"
label: Absence Text Value
name: absenceTextValue
required: false
type: TEXT
groupName: customGroup
- description: Input like '#FFFFFF' or 'red', 'yellow' etc.
label: Absence Icon Color (only usable if the icon is transparent)
name: absenceIconColor
required: false
type: TEXT
groupName: customGroup
- default: "false"
description: Display your own labels for the people
label: Person Label - Show on Card
name: personLabelShow
required: false
type: BOOLEAN
groupName: customGroup
- description: Labels for persons - to display Name; comma separated list
label: Person Labels List
name: personLabelArray
required: false
type: TEXT
groupName: customGroup
- description: Use oh:iconName (openHAB icon), f7:iconName (Framework7 icon),
material:iconName (Material icon) or iconify:iconSet:iconName; comma
separated list
label: Persons Icon List
name: personIconArray
required: false
type: TEXT
groupName: customGroup
- description: Absence person item - to display State; comma separated list
name: personItemList
required: false
type: TEXT
groupName: customGroup
- description: "Absence person - display time since absent or display the absence
text (default: false)"
label: Absence Time Person - Show on Card
name: personShowAbsentTime
required: false
type: BOOLEAN
groupName: customGroup
- description: Absence person - to display time since absence; comma separated list
name: personItemLastUpdateList
required: false
type: TEXT
groupName: customGroup
parameterGroups:
- name: cardGroup
label: Card Settings
description: All settings to customize the card layout
- name: iconGroup
label: Icon Settings
description: All settings to customize the icon
- name: headerGroup
label: Header Settings
description: All settings to customize the header area
- name: footerGroup
label: Footer Settings
description: All settings to customize the content area
- name: contentGroup
label: Content Settings
description: All settings to customize the content area
- name: customGroup
label: Custom Settings
description: All settings to customize the custom objects
timestamp: Dec 30, 2025, 6:35:57 PM
component: f7-card
config:
style:
--f7-card-bg-color: "=props.cardBgColor ? props.cardBgColor : (themeOptions.dark
=== 'dark' ? '#232324' : 'white')"
--f7-card-border-radius: "=props.cardBorderRadius ? (props.cardBorderRadius) + 'px' : '20px'"
--f7-card-margin-horizontal: 4px
--f7-card-margin-vertical: 4px
--f7-card-outline-border-color: "=props.cardBorderColor ? props.cardBorderColor
: (themeOptions.dark === 'dark' ? '#c95826' : '#c95826')"
background-color: var(--f7-card-bg-color)
background-image: "=props.cardBgImageShow== 'false' ? '' :
'linear-gradient(rgba(255,255,255,0.6), rgba(255,255,255,0.6)),
url(/static/' + props.cardBgImage + ')'"
border: "=props.cardBorderSize ? (props.cardBorderSize)+'px solid
var(--f7-card-outline-border-color)' : '6px solid
var(--f7-card-outline-border-color)'"
color: "=props.contentTextColor ? props.contentTextColor : (themeOptions.dark
=== 'dark' ? 'white' : 'black')"
font-size: "=props.contentTextSize ? (props.contentTextSize)+'px' : '18px'"
slots:
default:
- component: f7-card-header
config:
style:
--f7-card-header-border-color: transparent
--f7-card-header-font-size: "=props.headerTextSize ? (props.headerTextSize) + 'px' : '25px'"
--f7-card-header-font-weight: 800
--f7-card-header-min-height: "=props.headerShow == 'true' ? '35px' : '0px'"
--f7-card-header-text-color: "=props.headerTextColor ? props.headerTextColor :
(themeOptions.dark === 'dark' ? 'white' : 'black')"
justify-content: flex-start
margin-left: "=(Number.parseInt(props.cardBorderRadius) > 90) ? '30px' :
(Number.parseInt(props.cardBorderRadius) > 50) ? '10px' : '0px'"
slots:
default:
- component: oh-icon
config:
icon: "=props.iconName ? props.iconName : 'f7:house'"
style:
color: "=props.iconColor ? props.iconColor : (themeOptions.dark === 'dark' ?
'white' : 'black')"
padding-right: 10px
visible: "=props.iconShow ? props.iconShow : props.iconShow"
width: "=props.iconSize ? (props.iconSize) + 'px' : '30px'"
- component: Label
config:
text: "=props.headerText ? props.headerText : 'Header'"
visible: "=props.headerShow ? props.headerShow : props.headerShow"
- component: f7-card-content
config:
style:
align-items: center
display: flex
height: "=props.cardHeight ? (props.cardHeight) + 'px' : ''"
justify-content: center
margin-left: "=(Number.parseInt(props.cardBorderRadius) > 90) ? '30px' :
(Number.parseInt(props.cardBorderRadius) > 50) ? '10px' : '0px'"
margin-top: -10px
slots:
default:
- component: f7-block
config:
style:
margin-top: -10px
text-align: center
width: 100%
slots:
default:
- component: f7-row
slots:
default:
- component: oh-repeater
config:
for: listitem
fragment: true
in: =props.personLabelArray.split(",")
slots:
default:
- component: f7-col
slots:
default:
- component: Label
config:
text: =loop.listitem
visible: "=props.personLabelShow ? props.personLabelShow :
props.personLabelShow"
- component: f7-row
config:
style:
margin-top: 10px
slots:
default:
- component: oh-repeater
config:
for: listitem
fragment: true
in: =props.personIconArray.split(",")
slots:
default:
- component: f7-col
slots:
default:
- component: oh-icon
config:
action: analyzer
actionAnalyzerChartType: day
actionAnalyzerCoordSystem: time
actionAnalyzerItems:
- '=props.personItemList.split(",")[loop.listitem_idx]'
height: "=props.contentIconSize ? (props.contentIconSize) + 'px' : '30px'"
icon: =loop.listitem
style:
color: "=(@@loop.listitem == 'ON' ? (props.presentIconColor ?
props.presentIconColor : 'green') :
(props.absenceIconColor ?
props.absenceIconColor : 'red')) :
props.contentIconColor ?
props.contentIconColor :
(themeOptions.dark === 'dark' ?
'white' : 'black')"
margin-top: 5px
- component: f7-row
config:
class:
- text-align-center
slots:
default:
- component: oh-repeater
config:
for: listitem
fragment: true
in: =props.personItemList.split(",")
slots:
default:
- component: f7-col
slots:
default:
- component: Label
config:
style:
margin-top: 5px
text: "=@@loop.listitem == 'ON' ? (props.presentTextValue ?
props.presentTextValue : 'present')
:(props.personShowAbsentTime
? dayjs(items[props.personItemLastUpda\
teList.split(',')[loop.listitem_idx]].s\
tate).fromNow() :
(props.absenceTextValue ?
props.absenceTextValue : 'absent'))"
- component: f7-card-footer
config:
style:
--f7-card-footer-border-color: transparent
--f7-card-footer-font-size: "=props.footerTextSize ? (props.footerTextSize) + 'px' : '16px'"
--f7-card-footer-font-weight: 500
--f7-card-footer-min-height: "=props.footerShow == 'true' ? '20px' : '0px'"
--f7-card-footer-text-color: "=props.footerTextColor ? props.footerTextColor :
(themeOptions.dark === 'dark' ? 'white' : 'black')"
margin-left: "=(Number.parseInt(props.cardBorderRadius) > 90) ? '30px' :
(Number.parseInt(props.cardBorderRadius) > 50) ? '10px' : '0px'"
slots:
default:
- component: Label
config:
text: "=props.footerText ? props.footerText : 'Footer'"
visible: "=props.footerShow ? props.footerShow : props.footerShow"
'''