mirror of
https://github.com/home-assistant/frontend
synced 2024-09-30 15:52:53 +02:00
Clean up even more (#3074)
This commit is contained in:
parent
8df9ac9dfa
commit
1c17210948
@ -44,7 +44,7 @@ function transformXMLtoPolymer(name, xml) {
|
||||
|
||||
// Given an iconset name and icon names, generate a polymer iconset
|
||||
function generateIconset(name, iconNames) {
|
||||
const iconDefs = iconNames
|
||||
const iconDefs = Array.from(iconNames)
|
||||
.map((name) => {
|
||||
const iconDef = loadIcon(name);
|
||||
if (!iconDef) {
|
||||
@ -95,12 +95,15 @@ function findIcons(path, iconsetName) {
|
||||
}
|
||||
mapFiles(path, ".js", processFile);
|
||||
mapFiles(path, ".ts", processFile);
|
||||
return Array.from(icons);
|
||||
return icons;
|
||||
}
|
||||
|
||||
function genHassIcons() {
|
||||
const iconNames = findIcons("./src", "hass").concat(BUILT_IN_PANEL_ICONS);
|
||||
fs.existsSync(OUTPUT_DIR) || fs.mkdirSync(OUTPUT_DIR);
|
||||
const iconNames = findIcons("./src", "hass");
|
||||
BUILT_IN_PANEL_ICONS.forEach((name) => iconNames.add(name));
|
||||
if (!fs.existsSync(OUTPUT_DIR)) {
|
||||
fs.mkdirSync(OUTPUT_DIR);
|
||||
}
|
||||
fs.writeFileSync(HASS_OUTPUT_PATH, generateIconset("hass", iconNames));
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,13 @@ const {
|
||||
genMDIIcons,
|
||||
} = require("../../gulp/tasks/gen-icons.js");
|
||||
|
||||
const MENU_BUTTON_ICON = "menu";
|
||||
|
||||
function genHassioIcons() {
|
||||
const iconNames = findIcons("./src", "hassio").concat(MENU_BUTTON_ICON);
|
||||
const iconNames = findIcons("./src", "hassio");
|
||||
|
||||
for (const item of findIcons("../src", "hassio")) {
|
||||
iconNames.add(item);
|
||||
}
|
||||
|
||||
fs.writeFileSync("./hassio-icons.html", generateIconset("hassio", iconNames));
|
||||
}
|
||||
|
||||
|
@ -1,103 +0,0 @@
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import "../components/hassio-card-content";
|
||||
import "../resources/hassio-style";
|
||||
import NavigateMixin from "../../../src/mixins/navigate-mixin";
|
||||
|
||||
class HassioAddonRepository extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style hassio-style">
|
||||
paper-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
.not_available {
|
||||
opacity: 0.6;
|
||||
}
|
||||
a.repo {
|
||||
display: block;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[addons.length]]">
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
[[repo.name]]
|
||||
<div class="description">
|
||||
Maintained by [[repo.maintainer]]
|
||||
<a class="repo" href="[[repo.url]]" target="_blank"
|
||||
>[[repo.url]]</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[addons]]"
|
||||
as="addon"
|
||||
sort="sortAddons"
|
||||
>
|
||||
<paper-card class$="[[computeClass(addon)]]" on-click="addonTapped">
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
hass="[[hass]]"
|
||||
title="[[addon.name]]"
|
||||
description="[[addon.description]]"
|
||||
available="[[addon.available]]"
|
||||
icon="[[computeIcon(addon)]]"
|
||||
icon-title="[[computeIconTitle(addon)]]"
|
||||
icon-class="[[computeIconClass(addon)]]"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
repo: Object,
|
||||
addons: Array,
|
||||
};
|
||||
}
|
||||
|
||||
sortAddons(a, b) {
|
||||
return a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1;
|
||||
}
|
||||
|
||||
computeIcon(addon) {
|
||||
return addon.installed && addon.installed !== addon.version
|
||||
? "hassio:arrow-up-bold-circle"
|
||||
: "hassio:puzzle";
|
||||
}
|
||||
|
||||
computeIconTitle(addon) {
|
||||
if (addon.installed)
|
||||
return addon.installed !== addon.version
|
||||
? "New version available"
|
||||
: "Add-on is installed";
|
||||
return addon.available
|
||||
? "Add-on is not installed"
|
||||
: "Add-on is not available on your system";
|
||||
}
|
||||
|
||||
computeIconClass(addon) {
|
||||
if (addon.installed)
|
||||
return addon.installed !== addon.version ? "update" : "installed";
|
||||
return !addon.available ? "not_available" : "";
|
||||
}
|
||||
|
||||
computeClass(addon) {
|
||||
return !addon.available ? "not_available" : "";
|
||||
}
|
||||
|
||||
addonTapped(ev) {
|
||||
this.navigate(`/hassio/addon/${ev.model.addon.slug}`);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hassio-addon-repository", HassioAddonRepository);
|
112
hassio/src/addon-store/hassio-addon-repository.ts
Normal file
112
hassio/src/addon-store/hassio-addon-repository.ts
Normal file
@ -0,0 +1,112 @@
|
||||
import {
|
||||
css,
|
||||
TemplateResult,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
CSSResultArray,
|
||||
} from "lit-element";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
|
||||
import "../components/hassio-card-content";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import {
|
||||
HassioAddonInfo,
|
||||
HassioAddonRepository,
|
||||
} from "../../../src/data/hassio";
|
||||
import { navigate } from "../../../src/common/navigate";
|
||||
|
||||
class HassioAddonRepositoryEl extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public repo!: HassioAddonRepository;
|
||||
@property() public addons!: HassioAddonInfo[];
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
const repo = this.repo;
|
||||
return html`
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
${repo.name}
|
||||
<div class="description">
|
||||
Maintained by ${repo.maintainer}<br />
|
||||
<a class="repo" href=${repo.url} target="_blank">${repo.url}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${this.addons
|
||||
.sort((a, b) =>
|
||||
a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1
|
||||
)
|
||||
.map(
|
||||
(addon) => html`
|
||||
<paper-card
|
||||
.addon=${addon}
|
||||
class=${addon.available ? "" : "not_available"}
|
||||
@click=${this.addonTapped}
|
||||
>
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
.hass=${this.hass}
|
||||
.title=${addon.name}
|
||||
.description=${addon.description}
|
||||
.available=${addon.available}
|
||||
.icon=${this.computeIcon(addon)}
|
||||
.iconTitle=${this.computeIconTitle(addon)}
|
||||
.iconClass=${this.computeIconClass(addon)}
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
</paper-card>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private computeIcon(addon) {
|
||||
return addon.installed && addon.installed !== addon.version
|
||||
? "hassio:arrow-up-bold-circle"
|
||||
: "hassio:puzzle";
|
||||
}
|
||||
|
||||
private computeIconTitle(addon) {
|
||||
if (addon.installed) {
|
||||
return addon.installed !== addon.version
|
||||
? "New version available"
|
||||
: "Add-on is installed";
|
||||
}
|
||||
return addon.available
|
||||
? "Add-on is not installed"
|
||||
: "Add-on is not available on your system";
|
||||
}
|
||||
|
||||
private computeIconClass(addon) {
|
||||
if (addon.installed) {
|
||||
return addon.installed !== addon.version ? "update" : "installed";
|
||||
}
|
||||
return !addon.available ? "not_available" : "";
|
||||
}
|
||||
|
||||
private addonTapped(ev) {
|
||||
navigate(this, `/hassio/addon/${ev.currentTarget.addon.slug}`);
|
||||
}
|
||||
|
||||
static get styles(): CSSResultArray {
|
||||
return [
|
||||
hassioStyle,
|
||||
css`
|
||||
paper-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
.not_available {
|
||||
opacity: 0.6;
|
||||
}
|
||||
a.repo {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hassio-addon-repository", HassioAddonRepositoryEl);
|
@ -1,92 +0,0 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import "./hassio-addon-repository";
|
||||
import "./hassio-repositories-editor";
|
||||
|
||||
class HassioAddonStore extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
hassio-addon-repository {
|
||||
margin-top: 24px;
|
||||
}
|
||||
</style>
|
||||
<hassio-repositories-editor
|
||||
hass="[[hass]]"
|
||||
repos="[[repos]]"
|
||||
></hassio-repositories-editor>
|
||||
|
||||
<template is="dom-repeat" items="[[repos]]" as="repo" sort="sortRepos">
|
||||
<hassio-addon-repository
|
||||
hass="[[hass]]"
|
||||
repo="[[repo]]"
|
||||
addons="[[computeAddons(repo.slug)]]"
|
||||
></hassio-addon-repository>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
addons: Array,
|
||||
repos: Array,
|
||||
};
|
||||
}
|
||||
|
||||
ready() {
|
||||
super.ready();
|
||||
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
|
||||
this.loadData();
|
||||
}
|
||||
|
||||
apiCalled(ev) {
|
||||
if (ev.detail.success) {
|
||||
this.loadData();
|
||||
}
|
||||
}
|
||||
|
||||
sortRepos(a, b) {
|
||||
if (a.slug === "local") {
|
||||
return -1;
|
||||
}
|
||||
if (b.slug === "local") {
|
||||
return 1;
|
||||
}
|
||||
if (a.slug === "core") {
|
||||
return -1;
|
||||
}
|
||||
if (b.slug === "core") {
|
||||
return 1;
|
||||
}
|
||||
return a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1;
|
||||
}
|
||||
|
||||
computeAddons(repo) {
|
||||
return this.addons.filter(function(addon) {
|
||||
return addon.repository === repo;
|
||||
});
|
||||
}
|
||||
|
||||
loadData() {
|
||||
this.hass.callApi("get", "hassio/addons").then(
|
||||
(info) => {
|
||||
this.addons = info.data.addons;
|
||||
this.repos = info.data.repositories;
|
||||
},
|
||||
() => {
|
||||
this.addons = [];
|
||||
this.repos = [];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
refreshData() {
|
||||
this.hass.callApi("post", "hassio/addons/reload").then(() => {
|
||||
this.loadData();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hassio-addon-store", HassioAddonStore);
|
116
hassio/src/addon-store/hassio-addon-store.ts
Normal file
116
hassio/src/addon-store/hassio-addon-store.ts
Normal file
@ -0,0 +1,116 @@
|
||||
import "./hassio-addon-repository";
|
||||
import "./hassio-repositories-editor";
|
||||
import { TemplateResult, html } from "lit-html";
|
||||
import {
|
||||
LitElement,
|
||||
CSSResult,
|
||||
css,
|
||||
property,
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import {
|
||||
HassioAddonRepository,
|
||||
HassioAddonInfo,
|
||||
fetchHassioAddonsInfo,
|
||||
reloadHassioAddons,
|
||||
} from "../../../src/data/hassio";
|
||||
import "../../../src/layouts/loading-screen";
|
||||
|
||||
const sortRepos = (a: HassioAddonRepository, b: HassioAddonRepository) => {
|
||||
if (a.slug === "local") {
|
||||
return -1;
|
||||
}
|
||||
if (b.slug === "local") {
|
||||
return 1;
|
||||
}
|
||||
if (a.slug === "core") {
|
||||
return -1;
|
||||
}
|
||||
if (b.slug === "core") {
|
||||
return 1;
|
||||
}
|
||||
return a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1;
|
||||
};
|
||||
|
||||
class HassioAddonStore extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() private _addons?: HassioAddonInfo[];
|
||||
@property() private _repos?: HassioAddonRepository[];
|
||||
|
||||
public async refreshData() {
|
||||
this._repos = undefined;
|
||||
this._addons = undefined;
|
||||
await reloadHassioAddons(this.hass);
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this._addons || !this._repos) {
|
||||
return html`
|
||||
<loading-screen></loading-screen>
|
||||
`;
|
||||
}
|
||||
const repos: TemplateResult[] = [];
|
||||
|
||||
for (const repo of this._repos) {
|
||||
const addons = this._addons!.filter(
|
||||
(addon) => addon.repository === repo.slug
|
||||
);
|
||||
|
||||
if (addons.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
repos.push(html`
|
||||
<hassio-addon-repository
|
||||
.hass=${this.hass}
|
||||
.repo=${repo}
|
||||
.addons=${addons}
|
||||
></hassio-addon-repository>
|
||||
`);
|
||||
}
|
||||
|
||||
return html`
|
||||
<hassio-repositories-editor
|
||||
.hass=${this.hass}
|
||||
.repos=${this._repos}
|
||||
></hassio-repositories-editor>
|
||||
|
||||
${repos}
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
super.firstUpdated(changedProps);
|
||||
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
|
||||
this._loadData();
|
||||
}
|
||||
|
||||
private apiCalled(ev) {
|
||||
if (ev.detail.success) {
|
||||
this._loadData();
|
||||
}
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
try {
|
||||
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
|
||||
this._repos = addonsInfo.repositories;
|
||||
this._repos.sort(sortRepos);
|
||||
this._addons = addonsInfo.addons;
|
||||
} catch (err) {
|
||||
alert("Failed to fetch add-on info");
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
hassio-addon-repository {
|
||||
margin-top: 24px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hassio-addon-store", HassioAddonStore);
|
@ -1,120 +0,0 @@
|
||||
import "@polymer/iron-icon/iron-icon";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import "../../../src/components/buttons/ha-call-api-button";
|
||||
import "../components/hassio-card-content";
|
||||
import "../resources/hassio-style";
|
||||
|
||||
class HassioRepositoriesEditor extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style hassio-style">
|
||||
.add {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
iron-icon {
|
||||
color: var(--secondary-text-color);
|
||||
margin-right: 16px;
|
||||
display: inline-block;
|
||||
}
|
||||
paper-input {
|
||||
width: calc(100% - 49px);
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
Repositories
|
||||
<div class="description">
|
||||
Configure which add-on repositories to fetch data from:
|
||||
</div>
|
||||
</div>
|
||||
<template
|
||||
id="list"
|
||||
is="dom-repeat"
|
||||
items="[[repoList]]"
|
||||
as="repo"
|
||||
sort="sortRepos"
|
||||
>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
hass="[[hass]]"
|
||||
title="[[repo.name]]"
|
||||
description="[[repo.url]]"
|
||||
icon="hassio:github-circle"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/supervisor/options"
|
||||
data="[[computeRemoveRepoData(repoList, repo.url)]]"
|
||||
class="warning"
|
||||
>Remove</ha-call-api-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
<paper-card>
|
||||
<div class="card-content add">
|
||||
<iron-icon icon="hassio:github-circle"></iron-icon>
|
||||
<paper-input
|
||||
label="Add new repository by URL"
|
||||
value="{{repoUrl}}"
|
||||
></paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/supervisor/options"
|
||||
data="[[computeAddRepoData(repoList, repoUrl)]]"
|
||||
>Add</ha-call-api-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
repos: {
|
||||
type: Array,
|
||||
observer: "reposChanged",
|
||||
},
|
||||
repoList: Array,
|
||||
repoUrl: String,
|
||||
};
|
||||
}
|
||||
|
||||
reposChanged(repos) {
|
||||
this.repoList = repos.filter(
|
||||
(repo) => repo.slug !== "core" && repo.slug !== "local"
|
||||
);
|
||||
this.repoUrl = "";
|
||||
}
|
||||
|
||||
sortRepos(a, b) {
|
||||
return a.name < b.name ? -1 : 1;
|
||||
}
|
||||
|
||||
computeRemoveRepoData(repoList, url) {
|
||||
const list = repoList
|
||||
.filter((repo) => repo.url !== url)
|
||||
.map((repo) => repo.source);
|
||||
return { addons_repositories: list };
|
||||
}
|
||||
|
||||
computeAddRepoData(repoList, url) {
|
||||
const list = repoList ? repoList.map((repo) => repo.source) : [];
|
||||
list.push(url);
|
||||
return { addons_repositories: list };
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hassio-repositories-editor", HassioRepositoriesEditor);
|
148
hassio/src/addon-store/hassio-repositories-editor.ts
Normal file
148
hassio/src/addon-store/hassio-repositories-editor.ts
Normal file
@ -0,0 +1,148 @@
|
||||
import {
|
||||
LitElement,
|
||||
html,
|
||||
CSSResultArray,
|
||||
css,
|
||||
property,
|
||||
TemplateResult,
|
||||
customElement,
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import "@polymer/iron-icon/iron-icon";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import memoizeOne from "memoize-one";
|
||||
|
||||
import "../../../src/components/buttons/ha-call-api-button";
|
||||
import "../components/hassio-card-content";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import { HassioAddonRepository } from "../../../src/data/hassio";
|
||||
import { PolymerChangedEvent } from "../../../src/polymer-types";
|
||||
import { repeat } from "lit-html/directives/repeat";
|
||||
|
||||
@customElement("hassio-repositories-editor")
|
||||
class HassioRepositoriesEditor extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public repos!: HassioAddonRepository[];
|
||||
@property() private _repoUrl = "";
|
||||
|
||||
private _sortedRepos = memoizeOne((repos: HassioAddonRepository[]) =>
|
||||
repos
|
||||
.filter((repo) => repo.slug !== "core" && repo.slug !== "local")
|
||||
.sort((a, b) => (a.name < b.name ? -1 : 1))
|
||||
);
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
const repos = this._sortedRepos(this.repos);
|
||||
return html`
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
Repositories
|
||||
<div class="description">
|
||||
Configure which add-on repositories to fetch data from:
|
||||
</div>
|
||||
</div>
|
||||
${// Use repeat so that the fade-out from call-service-api-button
|
||||
// stays with the correct repo after we add/delete one.
|
||||
repeat(
|
||||
repos,
|
||||
(repo) => repo.slug,
|
||||
(repo) => html`
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
.hass=${this.hass}
|
||||
.title=${repo.name}
|
||||
.description=${repo.url}
|
||||
icon="hassio:github-circle"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
path="hassio/supervisor/options"
|
||||
.hass=${this.hass}
|
||||
.data=${this.computeRemoveRepoData(repos, repo.url)}
|
||||
class="warning"
|
||||
>
|
||||
Remove
|
||||
</ha-call-api-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`
|
||||
)}
|
||||
|
||||
<paper-card>
|
||||
<div class="card-content add">
|
||||
<iron-icon icon="hassio:github-circle"></iron-icon>
|
||||
<paper-input
|
||||
label="Add new repository by URL"
|
||||
.value=${this._repoUrl}
|
||||
@value-changed=${this._urlChanged}
|
||||
></paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
path="hassio/supervisor/options"
|
||||
.hass=${this.hass}
|
||||
.data=${this.computeAddRepoData(repos, this._repoUrl)}
|
||||
>
|
||||
Add
|
||||
</ha-call-api-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
super.updated(changedProps);
|
||||
|
||||
if (changedProps.has("repos")) {
|
||||
this._repoUrl = "";
|
||||
}
|
||||
}
|
||||
|
||||
private _urlChanged(ev: PolymerChangedEvent<string>) {
|
||||
this._repoUrl = ev.detail.value;
|
||||
}
|
||||
|
||||
private computeRemoveRepoData(repoList, url) {
|
||||
const list = repoList
|
||||
.filter((repo) => repo.url !== url)
|
||||
.map((repo) => repo.source);
|
||||
return { addons_repositories: list };
|
||||
}
|
||||
|
||||
private computeAddRepoData(repoList, url) {
|
||||
const list = repoList ? repoList.map((repo) => repo.source) : [];
|
||||
list.push(url);
|
||||
return { addons_repositories: list };
|
||||
}
|
||||
|
||||
static get styles(): CSSResultArray {
|
||||
return [
|
||||
hassioStyle,
|
||||
css`
|
||||
.add {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
iron-icon {
|
||||
color: var(--secondary-text-color);
|
||||
margin-right: 16px;
|
||||
display: inline-block;
|
||||
}
|
||||
paper-input {
|
||||
width: calc(100% - 49px);
|
||||
display: inline-block;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hassio-repositories-editor": HassioRepositoriesEditor;
|
||||
}
|
||||
}
|
@ -168,12 +168,18 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) {
|
||||
icon="hassio:arrow-up-bold-circle"
|
||||
icon-class="update"
|
||||
></hassio-card-content>
|
||||
<template is="dom-if" if="[[!addon.available]]">
|
||||
<p>This update is no longer compatible with your system.</p>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/update"
|
||||
>Update</ha-call-api-button
|
||||
disabled="[[!addon.available]]"
|
||||
>
|
||||
Update
|
||||
</ha-call-api-button
|
||||
>
|
||||
<template is="dom-if" if="[[addon.changelog]]">
|
||||
<mwc-button on-click="openChangelog">Changelog</mwc-button>
|
||||
|
@ -5,7 +5,6 @@ import "@polymer/paper-icon-button/paper-icon-button";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import "../../../src/resources/ha-style";
|
||||
import "./hassio-addon-audio";
|
||||
import "./hassio-addon-config";
|
||||
import "./hassio-addon-info";
|
||||
@ -15,7 +14,7 @@ import "./hassio-addon-network";
|
||||
class HassioAddonView extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
<style>
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
--paper-card-header-color: var(--primary-text-color);
|
||||
@ -48,16 +47,7 @@ class HassioAddonView extends PolymerElement {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<app-header-layout has-scrolling-region="">
|
||||
<app-header fixed="" slot="header">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hassio:arrow-left"
|
||||
on-click="backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">Hass.io: add-on details</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<hass-subpage header="Hass.io: add-on details" hassio>
|
||||
<div class="content">
|
||||
<hassio-addon-info
|
||||
hass="[[hass]]"
|
||||
@ -93,7 +83,7 @@ class HassioAddonView extends PolymerElement {
|
||||
></hassio-addon-logs>
|
||||
</template>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -141,10 +131,6 @@ class HassioAddonView extends PolymerElement {
|
||||
);
|
||||
}
|
||||
|
||||
backTapped() {
|
||||
history.back();
|
||||
}
|
||||
|
||||
_computeSlug(route) {
|
||||
return route.path.substr(1);
|
||||
}
|
||||
|
@ -1,90 +0,0 @@
|
||||
import "@polymer/iron-icon/iron-icon";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import "../../../src/components/ha-relative-time";
|
||||
|
||||
class HassioCardContent extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
iron-icon {
|
||||
margin-right: 16px;
|
||||
margin-top: 16px;
|
||||
float: left;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
iron-icon.update {
|
||||
color: var(--paper-orange-400);
|
||||
}
|
||||
iron-icon.running,
|
||||
iron-icon.installed {
|
||||
color: var(--paper-green-400);
|
||||
}
|
||||
iron-icon.hassupdate,
|
||||
iron-icon.snapshot {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
iron-icon.not_available {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.title {
|
||||
color: var(--primary-text-color);
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
.addition {
|
||||
color: var(--secondary-text-color);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 2.4em;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
ha-relative-time {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<iron-icon
|
||||
icon="[[icon]]"
|
||||
class\$="[[iconClass]]"
|
||||
title="[[iconTitle]]"
|
||||
></iron-icon>
|
||||
<div>
|
||||
<div class="title">[[title]]</div>
|
||||
<div class="addition">
|
||||
<template is="dom-if" if="[[description]]">
|
||||
[[description]]
|
||||
</template>
|
||||
<template is="dom-if" if="[[!available]]">
|
||||
(Not available)
|
||||
</template>
|
||||
<template is="dom-if" if="[[datetime]]">
|
||||
<ha-relative-time
|
||||
hass="[[hass]]"
|
||||
class="addition"
|
||||
datetime="[[datetime]]"
|
||||
></ha-relative-time>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
title: String,
|
||||
description: String,
|
||||
available: Boolean,
|
||||
datetime: String,
|
||||
icon: {
|
||||
type: String,
|
||||
value: "hass:help-circle",
|
||||
},
|
||||
iconTitle: String,
|
||||
iconClass: String,
|
||||
};
|
||||
}
|
||||
}
|
||||
customElements.define("hassio-card-content", HassioCardContent);
|
97
hassio/src/components/hassio-card-content.ts
Normal file
97
hassio/src/components/hassio-card-content.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import {
|
||||
LitElement,
|
||||
TemplateResult,
|
||||
html,
|
||||
CSSResult,
|
||||
css,
|
||||
property,
|
||||
customElement,
|
||||
} from "lit-element";
|
||||
import "@polymer/iron-icon/iron-icon";
|
||||
|
||||
import "../../../src/components/ha-relative-time";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
|
||||
@customElement("hassio-card-content")
|
||||
class HassioCardContent extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public title!: string;
|
||||
@property() public description?: string;
|
||||
@property() public available: boolean = true;
|
||||
@property() public datetime?: string;
|
||||
@property() public iconTitle?: string;
|
||||
@property() public iconClass?: string;
|
||||
@property() public icon = "hass:help-circle";
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
return html`
|
||||
<iron-icon
|
||||
class=${this.iconClass}
|
||||
.icon=${this.icon}
|
||||
.title=${this.iconTitle}
|
||||
></iron-icon>
|
||||
<div>
|
||||
<div class="title">${this.title}</div>
|
||||
<div class="addition">
|
||||
${this.description} ${this.available ? undefined : " (Not available"}
|
||||
${this.datetime
|
||||
? html`
|
||||
<ha-relative-time
|
||||
.hass=${this.hass}
|
||||
class="addition"
|
||||
.datetime=${this.datetime}
|
||||
></ha-relative-time>
|
||||
`
|
||||
: undefined}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
iron-icon {
|
||||
margin-right: 16px;
|
||||
margin-top: 16px;
|
||||
float: left;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
iron-icon.update {
|
||||
color: var(--paper-orange-400);
|
||||
}
|
||||
iron-icon.running,
|
||||
iron-icon.installed {
|
||||
color: var(--paper-green-400);
|
||||
}
|
||||
iron-icon.hassupdate,
|
||||
iron-icon.snapshot {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
iron-icon.not_available {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.title {
|
||||
color: var(--primary-text-color);
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
.addition {
|
||||
color: var(--secondary-text-color);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 2.4em;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
ha-relative-time {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hassio-card-content": HassioCardContent;
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import "./hassio-addons";
|
||||
import "./hassio-hass-update";
|
||||
import EventsMixin from "../../../src/mixins/events-mixin";
|
||||
|
||||
class HassioDashboard extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<hassio-hass-update
|
||||
hass="[[hass]]"
|
||||
hass-info="[[hassInfo]]"
|
||||
></hassio-hass-update>
|
||||
<hassio-addons
|
||||
hass="[[hass]]"
|
||||
addons="[[supervisorInfo.addons]]"
|
||||
></hassio-addons>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
supervisorInfo: Object,
|
||||
hassInfo: Object,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hassio-dashboard", HassioDashboard);
|
52
hassio/src/dashboard/hassio-dashboard.ts
Normal file
52
hassio/src/dashboard/hassio-dashboard.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import {
|
||||
LitElement,
|
||||
TemplateResult,
|
||||
html,
|
||||
CSSResult,
|
||||
css,
|
||||
property,
|
||||
customElement,
|
||||
} from "lit-element";
|
||||
import "./hassio-addons";
|
||||
import "./hassio-hass-update";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import {
|
||||
HassioSupervisorInfo,
|
||||
HassioHomeAssistantInfo,
|
||||
} from "../../../src/data/hassio";
|
||||
|
||||
@customElement("hassio-dashboard")
|
||||
class HassioDashboard extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public supervisorInfo!: HassioSupervisorInfo;
|
||||
@property() public hassInfo!: HassioHomeAssistantInfo;
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
return html`
|
||||
<div class="content">
|
||||
<hassio-hass-update
|
||||
.hass=${this.hass}
|
||||
.hassInfo=${this.hassInfo}
|
||||
></hassio-hass-update>
|
||||
<hassio-addons
|
||||
.hass=${this.hass}
|
||||
.addons=${this.supervisorInfo.addons}
|
||||
></hassio-addons>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hassio-dashboard": HassioDashboard;
|
||||
}
|
||||
}
|
@ -14,6 +14,9 @@ import {
|
||||
fetchHassioSupervisorInfo,
|
||||
fetchHassioHostInfo,
|
||||
fetchHassioHomeAssistantInfo,
|
||||
HassioSupervisorInfo,
|
||||
HassioHostInfo,
|
||||
HassioHomeAssistantInfo,
|
||||
} from "../../src/data/hassio";
|
||||
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
|
||||
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
|
||||
@ -54,9 +57,9 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
||||
},
|
||||
};
|
||||
|
||||
@property() private _supervisorInfo: any;
|
||||
@property() private _hostInfo: any;
|
||||
@property() private _hassInfo: any;
|
||||
@property() private _supervisorInfo: HassioSupervisorInfo;
|
||||
@property() private _hostInfo: HassioHostInfo;
|
||||
@property() private _hassInfo: HassioHomeAssistantInfo;
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
super.firstUpdated(changedProps);
|
||||
|
@ -23,6 +23,11 @@ import scrollToTarget from "../../src/common/dom/scroll-to-target";
|
||||
import { haStyle } from "../../src/resources/styles";
|
||||
import { HomeAssistant, Route } from "../../src/types";
|
||||
import { navigate } from "../../src/common/navigate";
|
||||
import {
|
||||
HassioSupervisorInfo,
|
||||
HassioHostInfo,
|
||||
HassioHomeAssistantInfo,
|
||||
} from "../../src/data/hassio";
|
||||
|
||||
const HAS_REFRESH_BUTTON = ["store", "snapshots"];
|
||||
|
||||
@ -30,9 +35,9 @@ const HAS_REFRESH_BUTTON = ["store", "snapshots"];
|
||||
class HassioPagesWithTabs extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public route!: Route;
|
||||
@property() public supervisorInfo!: any;
|
||||
@property() public hostInfo!: any;
|
||||
@property() public hassInfo!: any;
|
||||
@property() public supervisorInfo!: HassioSupervisorInfo;
|
||||
@property() public hostInfo!: HassioHostInfo;
|
||||
@property() public hassInfo!: HassioHomeAssistantInfo;
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
const page = this._page;
|
||||
|
@ -7,13 +7,18 @@ import { PolymerElement } from "@polymer/polymer";
|
||||
import { HomeAssistant } from "../../src/types";
|
||||
// Don't codesplit it, that way the dashboard always loads fast.
|
||||
import "./dashboard/hassio-dashboard";
|
||||
import {
|
||||
HassioSupervisorInfo,
|
||||
HassioHostInfo,
|
||||
HassioHomeAssistantInfo,
|
||||
} from "../../src/data/hassio";
|
||||
|
||||
@customElement("hassio-tabs-router")
|
||||
class HassioTabsRouter extends HassRouterPage {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public supervisorInfo: any;
|
||||
@property() public hostInfo: any;
|
||||
@property() public hassInfo: any;
|
||||
@property() public supervisorInfo: HassioSupervisorInfo;
|
||||
@property() public hostInfo: HassioHostInfo;
|
||||
@property() public hassInfo: HassioHomeAssistantInfo;
|
||||
|
||||
protected routerOptions: RouterOptions = {
|
||||
routes: {
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
import { HomeAssistant, Route } from "../../../src/types";
|
||||
import {
|
||||
createHassioSession,
|
||||
HassioAddon,
|
||||
HassioAddonDetails,
|
||||
fetchHassioAddonInfo,
|
||||
} from "../../../src/data/hassio";
|
||||
import "../../../src/layouts/hass-loading-screen";
|
||||
@ -20,24 +20,27 @@ import "../../../src/layouts/hass-subpage";
|
||||
@customElement("hassio-ingress-view")
|
||||
class HassioIngressView extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public route!: Route & { slug: string };
|
||||
@property() private _hasSession = false;
|
||||
@property() private _addon?: HassioAddon;
|
||||
@property() public route!: Route;
|
||||
@property() private _addon?: HassioAddonDetails;
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this._hasSession || !this._addon) {
|
||||
if (!this._addon) {
|
||||
return html`
|
||||
<hass-loading-screen rootnav></hass-loading-screen>
|
||||
`;
|
||||
}
|
||||
return html`
|
||||
<hass-subpage .header=${this._addon.name} hassio root>
|
||||
<a .href=${this._addon.ingress_url} slot="toolbar-icon" target="_blank">
|
||||
<paper-icon-button icon="hassio:open-in-new"></paper-icon-button>
|
||||
</a>
|
||||
<iframe src=${this._addon.ingress_url}></iframe>
|
||||
</hass-subpage>
|
||||
|
||||
const iframe = html`
|
||||
<iframe src=${this._addon.ingress_url}></iframe>
|
||||
`;
|
||||
|
||||
return location.search === "?kiosk"
|
||||
? iframe
|
||||
: html`
|
||||
<hass-subpage .header=${this._addon.name} hassio root>
|
||||
${iframe}
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
@ -53,32 +56,30 @@ class HassioIngressView extends LitElement {
|
||||
const oldAddon = oldRoute ? oldRoute.path.substr(1) : undefined;
|
||||
|
||||
if (addon && addon !== oldAddon) {
|
||||
this._createSession();
|
||||
this._fetchAddonInfo(addon);
|
||||
this._fetchData(addon);
|
||||
}
|
||||
}
|
||||
|
||||
private async _fetchAddonInfo(addonSlug: string) {
|
||||
private async _fetchData(addonSlug: string) {
|
||||
try {
|
||||
const addon = await fetchHassioAddonInfo(this.hass, addonSlug);
|
||||
if (addon.ingress) {
|
||||
this._addon = addon;
|
||||
} else {
|
||||
alert("This add-on does not support ingress.");
|
||||
history.back();
|
||||
const [addon] = await Promise.all([
|
||||
fetchHassioAddonInfo(this.hass, addonSlug).catch(() => {
|
||||
throw new Error("Failed to fetch add-on info");
|
||||
}),
|
||||
createHassioSession(this.hass).catch(() => {
|
||||
throw new Error("Failed to create an ingress session");
|
||||
}),
|
||||
]);
|
||||
|
||||
if (!addon.ingress) {
|
||||
throw new Error("This add-on does not support ingress");
|
||||
}
|
||||
} catch (err) {
|
||||
alert("Failed to fetch add-on info");
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
|
||||
private async _createSession() {
|
||||
try {
|
||||
await createHassioSession(this.hass);
|
||||
this._hasSession = true;
|
||||
this._addon = addon;
|
||||
} catch (err) {
|
||||
alert("Failed to generate a session");
|
||||
// tslint:disable-next-line
|
||||
console.error(err);
|
||||
alert(err.message || "Unknown error starting ingress.");
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
|
@ -1,56 +1,64 @@
|
||||
import { css } from "lit-element";
|
||||
|
||||
const documentContainer = document.createElement("template");
|
||||
documentContainer.setAttribute("style", "display: none;");
|
||||
|
||||
export const hassioStyle = css`
|
||||
.card-group {
|
||||
margin-top: 24px;
|
||||
}
|
||||
.card-group .title {
|
||||
color: var(--primary-text-color);
|
||||
font-size: 2em;
|
||||
padding-left: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.card-group .description {
|
||||
font-size: 0.5em;
|
||||
font-weight: 500;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.card-group paper-card {
|
||||
--card-group-columns: 4;
|
||||
width: calc(
|
||||
(100% - 12px * var(--card-group-columns)) / var(--card-group-columns)
|
||||
);
|
||||
margin: 4px;
|
||||
vertical-align: top;
|
||||
}
|
||||
@media screen and (max-width: 1200px) and (min-width: 901px) {
|
||||
.card-group paper-card {
|
||||
--card-group-columns: 3;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 900px) and (min-width: 601px) {
|
||||
.card-group paper-card {
|
||||
--card-group-columns: 2;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 600px) and (min-width: 0) {
|
||||
.card-group paper-card {
|
||||
width: 100%;
|
||||
margin: 4px 0;
|
||||
}
|
||||
.content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
ha-call-api-button {
|
||||
font-weight: 500;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
documentContainer.innerHTML = `<dom-module id="hassio-style">
|
||||
<template>
|
||||
<style>
|
||||
.card-group {
|
||||
margin-top: 24px;
|
||||
}
|
||||
.card-group .title {
|
||||
color: var(--primary-text-color);
|
||||
font-size: 2em;
|
||||
padding-left: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.card-group .description {
|
||||
font-size: 0.5em;
|
||||
font-weight: 500;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.card-group paper-card {
|
||||
--card-group-columns: 4;
|
||||
width: calc((100% - 12px * var(--card-group-columns)) / var(--card-group-columns));
|
||||
margin: 4px;
|
||||
vertical-align: top;
|
||||
}
|
||||
@media screen and (max-width: 1200px) and (min-width: 901px) {
|
||||
.card-group paper-card {
|
||||
--card-group-columns: 3;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 900px) and (min-width: 601px) {
|
||||
.card-group paper-card {
|
||||
--card-group-columns: 2;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 600px) and (min-width: 0) {
|
||||
.card-group paper-card {
|
||||
width: 100%;
|
||||
margin: 4px 0;
|
||||
}
|
||||
.content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
ha-call-api-button {
|
||||
font-weight: 500;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
${hassioStyle.toString()}
|
||||
</style>
|
||||
</template>
|
||||
</dom-module>`;
|
||||
|
@ -11,7 +11,7 @@ import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio
|
||||
class HassioHostInfo extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
<style>
|
||||
paper-card {
|
||||
display: inline-block;
|
||||
width: 400px;
|
||||
|
@ -9,7 +9,7 @@ import EventsMixin from "../../../src/mixins/events-mixin";
|
||||
class HassioSupervisorInfo extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
<style>
|
||||
paper-card {
|
||||
display: inline-block;
|
||||
width: 400px;
|
||||
|
@ -1,4 +1,3 @@
|
||||
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
@ -9,7 +8,7 @@ import "./hassio-supervisor-log";
|
||||
class HassioSystem extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
<style>
|
||||
.content {
|
||||
margin: 4px;
|
||||
color: var(--primary-text-color);
|
||||
|
@ -9,7 +9,22 @@ interface CreateSessionResponse {
|
||||
session: string;
|
||||
}
|
||||
|
||||
export interface HassioAddon {
|
||||
export interface HassioAddonInfo {
|
||||
name: string;
|
||||
slug: string;
|
||||
description: string;
|
||||
repository: "core" | "local" | string;
|
||||
version: string;
|
||||
installed: string | undefined;
|
||||
detached: boolean;
|
||||
available: boolean;
|
||||
build: boolean;
|
||||
url: string | null;
|
||||
icon: boolean;
|
||||
logo: boolean;
|
||||
}
|
||||
|
||||
export interface HassioAddonDetails {
|
||||
name: string;
|
||||
slug: string;
|
||||
description: string;
|
||||
@ -64,6 +79,29 @@ export interface HassioAddon {
|
||||
ingress_url: null | string;
|
||||
}
|
||||
|
||||
export interface HassioAddonRepository {
|
||||
slug: string;
|
||||
name: string;
|
||||
source: string;
|
||||
url: string;
|
||||
maintainer: string;
|
||||
}
|
||||
|
||||
export interface HassioAddonsInfo {
|
||||
addons: HassioAddonInfo[];
|
||||
repositories: HassioAddonRepository[];
|
||||
}
|
||||
export interface HassioHassOSInfo {
|
||||
version: string;
|
||||
version_cli: string;
|
||||
version_latest: string;
|
||||
version_cli_latest: string;
|
||||
board: "ova" | "rpi";
|
||||
}
|
||||
export type HassioHomeAssistantInfo = any;
|
||||
export type HassioSupervisorInfo = any;
|
||||
export type HassioHostInfo = any;
|
||||
|
||||
const hassioApiResultExtractor = <T>(response: HassioResponse<T>) =>
|
||||
response.data;
|
||||
|
||||
@ -77,22 +115,41 @@ export const createHassioSession = async (hass: HomeAssistant) => {
|
||||
};path=/api/hassio_ingress/`;
|
||||
};
|
||||
|
||||
export const reloadHassioAddons = (hass: HomeAssistant) =>
|
||||
hass
|
||||
.callApi<HassioResponse<unknown>>("POST", `hassio/addons/reload`)
|
||||
.then(hassioApiResultExtractor);
|
||||
|
||||
export const fetchHassioAddonsInfo = (hass: HomeAssistant) =>
|
||||
hass
|
||||
.callApi<HassioResponse<HassioAddonsInfo>>("GET", `hassio/addons`)
|
||||
.then(hassioApiResultExtractor);
|
||||
|
||||
export const fetchHassioAddonInfo = (hass: HomeAssistant, addon: string) =>
|
||||
hass
|
||||
.callApi<HassioResponse<HassioAddon>>("GET", `hassio/addons/${addon}/info`)
|
||||
.callApi<HassioResponse<HassioAddonDetails>>(
|
||||
"GET",
|
||||
`hassio/addons/${addon}/info`
|
||||
)
|
||||
.then(hassioApiResultExtractor);
|
||||
|
||||
export const fetchHassioSupervisorInfo = (hass: HomeAssistant) =>
|
||||
hass
|
||||
.callApi<HassioResponse<any>>("GET", "hassio/supervisor/info")
|
||||
.callApi<HassioResponse<HassioSupervisorInfo>>(
|
||||
"GET",
|
||||
"hassio/supervisor/info"
|
||||
)
|
||||
.then(hassioApiResultExtractor);
|
||||
|
||||
export const fetchHassioHostInfo = (hass: HomeAssistant) =>
|
||||
hass
|
||||
.callApi<HassioResponse<any>>("GET", "hassio/host/info")
|
||||
.callApi<HassioResponse<HassioHostInfo>>("GET", "hassio/host/info")
|
||||
.then(hassioApiResultExtractor);
|
||||
|
||||
export const fetchHassioHomeAssistantInfo = (hass: HomeAssistant) =>
|
||||
hass
|
||||
.callApi<HassioResponse<any>>("GET", "hassio/homeassistant/info")
|
||||
.callApi<HassioResponse<HassioHomeAssistantInfo>>(
|
||||
"GET",
|
||||
"hassio/homeassistant/info"
|
||||
)
|
||||
.then(hassioApiResultExtractor);
|
||||
|
@ -122,7 +122,10 @@ export class HassRouterPage extends UpdatingElement {
|
||||
: Promise.resolve();
|
||||
|
||||
// Check when loading the page source failed.
|
||||
loadProm.catch(() => {
|
||||
loadProm.catch((err) => {
|
||||
// tslint:disable-next-line
|
||||
console.error("Error loading page", newPage, err);
|
||||
|
||||
// Verify that we're still trying to show the same page.
|
||||
if (this._currentPage !== newPage) {
|
||||
return;
|
||||
|
35
src/layouts/loading-screen.ts
Normal file
35
src/layouts/loading-screen.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import "@polymer/paper-spinner/paper-spinner-lite";
|
||||
import {
|
||||
LitElement,
|
||||
TemplateResult,
|
||||
html,
|
||||
css,
|
||||
customElement,
|
||||
CSSResult,
|
||||
} from "lit-element";
|
||||
|
||||
@customElement("loading-screen")
|
||||
class LoadingScreen extends LitElement {
|
||||
protected render(): TemplateResult | void {
|
||||
return html`
|
||||
<paper-spinner-lite active></paper-spinner-lite>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
:host {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"loading-screen": LoadingScreen;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user