Add addon store

This commit is contained in:
Paulus Schoutsen 2017-05-01 23:41:28 -07:00
parent ce95af99fe
commit 110f152e23
7 changed files with 374 additions and 42 deletions

View File

@ -0,0 +1,70 @@
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<dom-module id="hassio-addon-repository">
<template>
<style include="iron-flex ha-style">
:host,
paper-card {
display: block;
}
paper-item {
cursor: pointer;
}
</style>
<paper-card heading='[[repo.name]]'>
<template is='dom-if' if='[[computeShowIntro(repo)]]'>
<div class='card-content'>
<template is='dom-if' if='[[repo.maintainer]]'>
Maintained by [[repo.maintainer]].
</template>
<template is='dom-if' if='[[repo.url]]'>
<a href='[[repo.url]]' target='_blank'>Visit repository website.</a>
</template>
</div>
</template>
<template is='dom-repeat' items='[[addons]]' as='addon'>
<paper-item>
<paper-item-body two-line on-tap='addonTapped'>
<div>[[addon.name]]</div>
<div secondary>[[addon.description]]</div>
</paper-item-body>
[[computeInstallStatus(addon)]]
</paper-item>
</template>
</paper-card>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-addon-repository',
properties: {
repo: {
type: Object,
},
addons: {
type: Array,
}
},
computeShowIntro: function (repo) {
return repo.url || repo.maintainer;
},
computeInstallStatus: function (addon) {
return addon.installed || 'Not installed';
},
addonTapped: function (ev) {
this.fire('hassio-select-addon', { addon: this.addons[ev.model.index].slug });
ev.target.blur();
},
});
</script>

View File

@ -0,0 +1,141 @@
<link rel="import" href="../../../bower_components/polymer/polymer.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/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../src/components/ha-menu-button.html">
<link rel="import" href="./hassio-repositories-editor.html">
<link rel="import" href="./hassio-addon-repository.html">
<dom-module id="hassio-addon-store">
<template>
<style include="iron-flex ha-style">
paper-card {
display: block;
}
.content {
padding: 24px 0 32px;
max-width: 600px;
margin: 0 auto;
}
hassio-addon-repository {
margin-top: 24px;
}
</style>
<app-header-layout has-scrolling-region>
<app-header fixed>
<app-toolbar>
<paper-icon-button
icon='mdi:arrow-left'
on-tap='backTapped'
></paper-icon-button>
<div main-title>Hass.io Add-Ons</div>
<paper-icon-button
icon="mdi:refresh"
on-tap="refreshTapped"
></paper-icon-button>
</app-toolbar>
</app-header>
<div class='content'>
<hassio-repositories-editor
hass='[[hass]]'
repos='[[supervisorInfo.addons_repositories]]'
></hassio-repositories-editor>
<template is='dom-repeat' items='[[repos]]' as='repo'>
<hassio-addon-repository
repo='[[repo]]'
addons='[[computeAddOns(repo.slug)]]'
></hassio-addon-repository>
</template>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
Polymer({
_coreRepos: [{
slug: 'core',
name: 'Built-in Add-Ons',
url: 'https://home-assistant.io/addons',
maintainer: 'Home Assistant authors',
}],
is: 'hassio-addon-store',
properties: {
hass: {
type: Object,
},
narrow: {
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
addons: {
type: Array,
value: [],
},
repos: {
type: Array,
value: []
},
supervisorInfo: {
type: Object,
}
},
listeners: {
'hass-api-called': 'apiCalled',
},
apiCalled: function (ev) {
if (ev.detail.success) {
this.loadData();
}
},
attached: function () {
this.loadData();
},
loadData: function () {
this.hass.callApi('get', 'hassio/supervisor/addons')
.then(function (info) {
this.addons = info.data.addons;
this.repos = this._coreRepos.concat(info.data.repositories);
}.bind(this), function () {
this.addons = [];
this.repos = [];
}.bind(this));
},
computeAddOns: function (repo) {
return this.addons.filter(function (addon) {
return addon.repository === repo;
});
},
refreshTapped: function () {
this.hass.callApi('post', 'hassio/supervisor/reload')
.then(function () {
this.loadData();
}.bind(this));
},
backTapped: function () {
this.fire('hassio-select-addon', { addon: null });
},
});
</script>

View File

@ -0,0 +1,67 @@
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
<link rel="import" href="../../../src/components/buttons/ha-call-api-button.html">
<dom-module id="hassio-repositories-editor">
<template>
<style include="ha-style">
:host {
display: block;
}
paper-card {
display: block;
}
iron-autogrow-textarea {
width: 100%;
}
</style>
<paper-card heading='Add-On Repositories'>
<div class="card-content">
<p>Configure which add-on repositories to fetch data from. One repository per line.</p>
<iron-autogrow-textarea value="{{options}}"></iron-autogrow-textarea>
</div>
<div class="card-actions">
<ha-call-api-button
hass='[[hass]]'
data='[[computeOptionsData(options)]]'
path="hassio/supervisor/options"
>Save</ha-call-api-button>
</div>
</paper-card>
</template>
</dom-module>
<script>
Polymer({
is: 'hassio-repositories-editor',
properties: {
hass: {
type: Object,
},
options: {
type: String,
value: '',
},
repos: {
type: Array,
value: [],
observer: 'reposChanged',
},
},
reposChanged: function (repos) {
this.options = repos.join('\n');
},
computeOptionsData: function (options) {
return {
addons_repositories: options.split('\n'),
};
},
});
</script>

View File

@ -24,7 +24,7 @@
</style> </style>
<paper-card heading='Info'> <paper-card heading='Info'>
<div class="card-content"> <div class="card-content">
<div>[[addonInfo.description]]</div> <p>[[addonInfo.description]]</p>
<table class='info'> <table class='info'>
<tr> <tr>
<td>Installed</td> <td>Installed</td>

View File

@ -17,17 +17,15 @@
} }
</style> </style>
<paper-card heading="Installed Addons"> <paper-card heading="Installed Addons">
<div class="card-content"> <template is='dom-repeat' items='[[data]]' as='addon'>
<template is='dom-repeat' items='[[data]]' as='addon'> <paper-item>
<paper-item> <paper-item-body two-line on-tap='addonTapped'>
<paper-item-body two-line on-tap='addonTapped'> <div>[[addon.name]]</div>
<div>[[addon.name]]</div> <div secondary>[[addon.description]]</div>
<div secondary>[[addon.description]]</div> </paper-item-body>
</paper-item-body> [[addon.installed]]
[[computeInstallStatus(addon)]] </paper-item>
</paper-item> </template>
</template>
</div>
</paper-card> </paper-card>
</template> </template>
</dom-module> </dom-module>
@ -56,10 +54,6 @@ Polymer({
}, },
}, },
computeInstallStatus(addon) {
return addon.installed || 'Not installed';
},
addonTapped: function (ev) { addonTapped: function (ev) {
this.fire('hassio-select-addon', { addon: this.data[ev.model.index].slug }); this.fire('hassio-select-addon', { addon: this.data[ev.model.index].slug });
ev.target.blur(); ev.target.blur();

View File

@ -3,6 +3,7 @@
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.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-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../src/components/ha-menu-button.html"> <link rel="import" href="../../../src/components/ha-menu-button.html">
@ -36,6 +37,10 @@
<app-toolbar> <app-toolbar>
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button> <ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
<div main-title>Hass.io</div> <div main-title>Hass.io</div>
<paper-icon-button
icon="mdi:shopping"
on-tap="storeTapped"
></paper-icon-button>
</app-toolbar> </app-toolbar>
</app-header> </app-header>
@ -100,5 +105,9 @@ Polymer({
value: {}, value: {},
}, },
}, },
storeTapped: function () {
this.fire('hassio-show-store');
},
}); });
</script> </script>

View File

@ -2,6 +2,7 @@
<link rel="import" href="./dashboard/hassio-dashboard.html"> <link rel="import" href="./dashboard/hassio-dashboard.html">
<link rel="import" href="./addon-view/hassio-addon-view.html"> <link rel="import" href="./addon-view/hassio-addon-view.html">
<link rel="import" href="./addon-store/hassio-addon-store.html">
<link rel="import" href="./hassio-loading.html"> <link rel="import" href="./hassio-loading.html">
<link rel="import" href="./hassio-data.html"> <link rel="import" href="./hassio-data.html">
@ -20,34 +21,42 @@
host='{{hostInfo}}' host='{{hostInfo}}'
></hassio-data> ></hassio-data>
<template is='dom-if' if='[[!loaded]]'> <template is='dom-if' if='[[dashboardSelected(currentPage)]]'>
<hassio-loading <template is='dom-if' if='[[!loaded]]'>
narrow='[[narrow]]' <hassio-loading
hass='[[hass]]' narrow='[[narrow]]'
show-menu='[[showMenu]]'
></hassio-loading>
</template>
<template is='dom-if' if='[[loaded]]' restamp>
<template is='dom-if' if='[[addon]]'>
<hassio-addon-view
hass='[[hass]]' hass='[[hass]]'
supervisor-info='[[supervisorInfo]]' show-menu='[[showMenu]]'
host-info='[[hostInfo]]' ></hassio-loading>
addon='[[addon]]'
></hassio-addon-view>
</template> </template>
<template is='dom-if' if='[[loaded]]'>
<template is='dom-if' if='[[!addon]]'>
<hassio-dashboard <hassio-dashboard
hass='[[hass]]' hass='[[hass]]'
narrow='[[narrow]]' narrow='[[narrow]]'
show-menu='[[showMenu]]' show-menu='[[showMenu]]'
supervisor-info='{{supervisorInfo}}' supervisor-info='[[supervisorInfo]]'
host-info='{{hostInfo}}' host-info='[[hostInfo]]'
hass-info='[[hassInfo]]' hass-info='[[hassInfo]]'
></hassio-dashboard> ></hassio-dashboard>
</template> </template>
</template> </template>
<template is='dom-if' if='[[addonViewSelected(currentPage)]]' restamp>
<hassio-addon-view
hass='[[hass]]'
supervisor-info='[[supervisorInfo]]'
host-info='[[hostInfo]]'
addon='[[addon]]'
></hassio-addon-view>
</template>
<template is='dom-if' if='[[addonStoreSelected(currentPage)]]'>
<hassio-addon-store
id='addon-store'
hass='[[hass]]'
supervisor-info='[[supervisorInfo]]'
></hassio-addon-store>
</template>
</template> </template>
</dom-module> </dom-module>
@ -97,16 +106,29 @@ Polymer({
loaded: { loaded: {
type: Boolean, type: Boolean,
computed: 'computeIsLoaded(supervisorInfo, hostInfo, hassInfo, forceLoading)', computed: 'computeIsLoaded(supervisorInfo, hostInfo, hassInfo, forceLoading)',
} },
currentPage: {
type: String,
value: 'dashboard',
},
lastPage: {
type: String,
value: 'dashboard',
},
}, },
listeners: { listeners: {
'hassio-select-addon': 'addonSelected', 'hassio-select-addon': 'addonSelected',
'hassio-show-store': 'showStore',
'hass-api-called': 'apiCalled', 'hass-api-called': 'apiCalled',
}, },
apiCalled: function () { apiCalled: function (ev) {
this.$.data.refresh(); if (ev.detail.success) {
this.$.data.refresh();
}
}, },
computeIsLoaded: function (supervisorInfo, hostInfo, hassInfo, forceLoading) { computeIsLoaded: function (supervisorInfo, hostInfo, hassInfo, forceLoading) {
@ -117,11 +139,40 @@ Polymer({
}, },
addonSelected: function (ev) { addonSelected: function (ev) {
this.forceLoading = true; var addon = ev.detail.addon;
setTimeout(function () {
this.addon = ev.detail.addon; if (this.currentPage === this.lastPage) {
this.forceLoading = false; this.lastPage = 'dashboard';
}.bind(this), 0); }
if (addon) {
this.lastPage = this.currentPage;
this.currentPage = 'addon-view';
this.addon = addon;
} else {
this.currentPage = this.lastPage;
// Give time to cleanup the addon-view panel or it crashes
setTimeout(function () {
this.addon = addon;
}.bind(this), 0);
}
}, },
showStore: function () {
this.currentPage = 'addon-store';
},
dashboardSelected: function (currentPage) {
return currentPage === 'dashboard';
},
addonStoreSelected: function (currentPage) {
return currentPage === 'addon-store';
},
addonViewSelected: function (currentPage) {
return currentPage === 'addon-view';
},
}); });
</script> </script>