mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-09 10:26:35 +00:00
Add Initial Mailbox panel and sensor (#319)
* Add Initial Mailbox panel * Use sha rather than index to lookup mp3 file * Popups for audio and delete-confirmation. Don't load all MP3s on page load * Show duration of message * Reload messages on change * eslint fixes * Wrap transcription text. Use 2nd-row per entry for transcription. Table consumes 100% of window height * Update to support mailbox component * Use mailbox component state instead of sensor state. Fix a bug in delete * Display mailbox entity * Use events to trigger mailbox updates * Support multiple mailbox platforms * Use REST API for mailbox deletion * Fix linting issues * Make dialogs reactive * Replace vaadin-grid with paper-items * 1st attempt at truncating lines to two columns * Apply requested changes from review * Clean up + Lint
This commit is contained in:
parent
2e1d3e1fa7
commit
58e2781412
260
panels/mailbox/ha-panel-mailbox.html
Normal file
260
panels/mailbox/ha-panel-mailbox.html
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
<link rel='import' href='../../bower_components/polymer/polymer.html'>
|
||||||
|
|
||||||
|
<link rel='import' href='../../bower_components/paper-button/paper-button.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-dialog/paper-dialog.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-input/paper-textarea.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-item/paper-item-body.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-card/paper-card.html'>
|
||||||
|
|
||||||
|
<link rel='import' href='../../bower_components/app-layout/app-header-layout/app-header-layout.html'>
|
||||||
|
<link rel='import' href='../../bower_components/app-layout/app-header/app-header.html'>
|
||||||
|
<link rel='import' href='../../bower_components/app-layout/app-toolbar/app-toolbar.html'>
|
||||||
|
<link rel="import" href="../../bower_components/app-storage/app-localstorage/app-localstorage-document.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../../bower_components/vaadin-combo-box/vaadin-combo-box.html">
|
||||||
|
|
||||||
|
<link rel='import' href='../../src/components/ha-menu-button.html'>
|
||||||
|
<link rel='import' href='../../src/resources/ha-style.html'>
|
||||||
|
|
||||||
|
|
||||||
|
<dom-module id='ha-panel-mailbox'>
|
||||||
|
<template>
|
||||||
|
<style include='ha-style'>
|
||||||
|
:host {
|
||||||
|
-ms-user-select: initial;
|
||||||
|
-webkit-user-select: initial;
|
||||||
|
-moz-user-select: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 16px;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
@apply(--paper-font-title);
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
paper-dialog {
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mp3dialog paper-icon-button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 450px) {
|
||||||
|
paper-dialog {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: calc(100% - 64px);
|
||||||
|
|
||||||
|
position: fixed !important;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
overflow: scroll;
|
||||||
|
border-bottom-left-radius: 0px;
|
||||||
|
border-bottom-right-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
width: auto;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<app-header-layout has-scrolling-region>
|
||||||
|
<app-header slot="header" fixed>
|
||||||
|
<app-toolbar>
|
||||||
|
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||||
|
<div main-title>Mailbox</div>
|
||||||
|
</app-toolbar>
|
||||||
|
</app-header>
|
||||||
|
<div class='content'>
|
||||||
|
<paper-card>
|
||||||
|
<template is='dom-if' if='[[!_messages.length]]'>
|
||||||
|
<div class='card-content'>
|
||||||
|
You do not have any messages.
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template is='dom-repeat' items='[[_messages]]'>
|
||||||
|
<paper-item on-tap='openMP3Dialog'>
|
||||||
|
<paper-item-body style="width:100%" two-line>
|
||||||
|
<div class="row">
|
||||||
|
<div>[[item.caller]]</div>
|
||||||
|
<div class="tip">[[item.duration]] secs</div>
|
||||||
|
</div>
|
||||||
|
<div secondary>
|
||||||
|
<span class="date">[[item.timestamp]]</span> - [[item.message]]
|
||||||
|
</div>
|
||||||
|
</paper-item-body>
|
||||||
|
</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-card>
|
||||||
|
</div>
|
||||||
|
</app-header-layout>
|
||||||
|
|
||||||
|
<paper-dialog with-backdrop id="mp3dialog" on-iron-overlay-closed="_mp3Closed">
|
||||||
|
<h2>
|
||||||
|
Message Playback
|
||||||
|
<paper-icon-button
|
||||||
|
on-tap='openDeleteDialog'
|
||||||
|
icon='mdi:delete'
|
||||||
|
></paper-icon-button>
|
||||||
|
</h2>
|
||||||
|
<div id="transcribe">text</div>
|
||||||
|
<div>
|
||||||
|
<audio id="mp3" preload="none" controls> <source id="mp3src" src="" type="audio/mpeg"></audio>
|
||||||
|
</div>
|
||||||
|
</paper-dialog>
|
||||||
|
|
||||||
|
<paper-dialog with-backdrop id="confirmdel">
|
||||||
|
<h2>Delete Message</h2>
|
||||||
|
<p>Are you sure you want to delete this message?</p>
|
||||||
|
<div class="buttons">
|
||||||
|
<paper-button dialog-dismiss>Decline</paper-button>
|
||||||
|
<paper-button dialog-confirm autofocus on-tap="deleteSelected">Accept</paper-button>
|
||||||
|
</div>
|
||||||
|
</paper-dialog>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Polymer({
|
||||||
|
is: 'ha-panel-mailbox',
|
||||||
|
properties: {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
narrow: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
showMenu: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
platforms: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
_messages: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
|
||||||
|
currentMessage: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
attached: function () {
|
||||||
|
this.hassChanged = this.hassChanged.bind(this);
|
||||||
|
this.hass.connection.subscribeEvents(this.hassChanged, 'mailbox_updated')
|
||||||
|
.then(function (unsub) { this._unsubEvents = unsub; }.bind(this));
|
||||||
|
this.computePlatforms().then(function (platforms) {
|
||||||
|
this.platforms = platforms;
|
||||||
|
this.hassChanged();
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
detached: function () {
|
||||||
|
if (this._unsubEvents) this._unsubEvents();
|
||||||
|
},
|
||||||
|
|
||||||
|
hassChanged: function () {
|
||||||
|
if (!this._messages) {
|
||||||
|
this._messages = [];
|
||||||
|
}
|
||||||
|
this.getMessages().then(function (items) {
|
||||||
|
this._messages = items;
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
openMP3Dialog: function (event) {
|
||||||
|
var platform = event.model.item.platform;
|
||||||
|
this.currentMessage = event.model.item;
|
||||||
|
this.$.mp3dialog.open();
|
||||||
|
this.$.mp3src.src = '/api/mailbox/media/' + platform + '/' + event.model.item.sha;
|
||||||
|
this.$.transcribe.innerText = event.model.item.message;
|
||||||
|
this.$.mp3.load();
|
||||||
|
this.$.mp3.play();
|
||||||
|
},
|
||||||
|
|
||||||
|
_mp3Closed: function () {
|
||||||
|
this.$.mp3.pause();
|
||||||
|
},
|
||||||
|
|
||||||
|
openDeleteDialog: function () {
|
||||||
|
this.$.confirmdel.open();
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteSelected: function () {
|
||||||
|
var msg = this.currentMessage;
|
||||||
|
this.hass.callApi('DELETE', 'mailbox/delete/' + msg.platform + '/' + msg.sha);
|
||||||
|
this.$.mp3dialog.close();
|
||||||
|
},
|
||||||
|
getMessages: function () {
|
||||||
|
const items = this.platforms.map(function (platform) {
|
||||||
|
return this.hass.callApi('GET', 'mailbox/messages/' + platform).then(function (values) {
|
||||||
|
var platformItems = [];
|
||||||
|
var arrayLength = values.length;
|
||||||
|
for (var i = 0; i < arrayLength; i++) {
|
||||||
|
var datetime = window.hassUtil.formatDateTime(new Date(values[i].info.origtime * 1000));
|
||||||
|
platformItems.push({
|
||||||
|
timestamp: datetime,
|
||||||
|
caller: values[i].info.callerid,
|
||||||
|
message: values[i].text,
|
||||||
|
sha: values[i].sha,
|
||||||
|
duration: values[i].info.duration,
|
||||||
|
platform: platform
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return platformItems;
|
||||||
|
});
|
||||||
|
}.bind(this));
|
||||||
|
return Promise.all(items).then(function (platformItems) {
|
||||||
|
var arrayLength = items.length;
|
||||||
|
var final = [];
|
||||||
|
for (var i = 0; i < arrayLength; i++) {
|
||||||
|
final = final.concat(platformItems[i]);
|
||||||
|
}
|
||||||
|
final.sort(function (a, b) {
|
||||||
|
return new Date(b.timestamp) - new Date(a.timestamp);
|
||||||
|
});
|
||||||
|
return final;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
computePlatforms: function () {
|
||||||
|
return this.hass.callApi('GET', 'mailbox/platforms');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
@ -106,6 +106,7 @@
|
|||||||
alarm_control_panel: 3,
|
alarm_control_panel: 3,
|
||||||
sensor: 5,
|
sensor: 5,
|
||||||
binary_sensor: 6,
|
binary_sensor: 6,
|
||||||
|
mailbox: 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getPriority(domain) {
|
function getPriority(domain) {
|
||||||
|
@ -302,6 +302,9 @@ window.hassUtil.domainIcon = function (domain, state) {
|
|||||||
case 'lock':
|
case 'lock':
|
||||||
return state && state === 'unlocked' ? 'mdi:lock-open' : 'mdi:lock';
|
return state && state === 'unlocked' ? 'mdi:lock-open' : 'mdi:lock';
|
||||||
|
|
||||||
|
case 'mailbox':
|
||||||
|
return 'mdi:mailbox';
|
||||||
|
|
||||||
case 'media_player':
|
case 'media_player':
|
||||||
return state && state !== 'off' && state !== 'idle' ?
|
return state && state !== 'off' && state !== 'idle' ?
|
||||||
'mdi:cast-connected' : 'mdi:cast';
|
'mdi:cast-connected' : 'mdi:cast';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user