mirror of
https://github.com/house-of-abbey/GarminHomeAssistant.git
synced 2025-06-16 03:18:35 +00:00
Error handling
This commit is contained in:
@ -121,6 +121,11 @@
|
|||||||
border-radius: 0.25em;
|
border-radius: 0.25em;
|
||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: var(--ctp-mocha-text);
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
border: 1px solid var(--ctp-mocha-teal);
|
border: 1px solid var(--ctp-mocha-teal);
|
||||||
@ -169,14 +174,19 @@
|
|||||||
|
|
||||||
button.icon {
|
button.icon {
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
padding: 0.1em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 1.5em;
|
width: 1.8em;
|
||||||
height: 1.5em;
|
height: 1.8em;
|
||||||
background-color: transparent;
|
background-color: var(--ctp-mocha-surface1);
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--ctp-mocha-red);
|
background-color: var(--ctp-mocha-overlay1);
|
||||||
}
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
@ -191,10 +201,18 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
&[icon='close']::before {
|
&[icon='close'] {
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--ctp-mocha-red);
|
||||||
|
}
|
||||||
|
&::before {
|
||||||
background-image: url(https://fonts.gstatic.com/s/i/short-term/release/materialsymbolsoutlined/close/default/48px.svg);
|
background-image: url(https://fonts.gstatic.com/s/i/short-term/release/materialsymbolsoutlined/close/default/48px.svg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&[icon='download']::before {
|
||||||
|
background-image: url(https://fonts.gstatic.com/s/i/short-term/release/materialsymbolsoutlined/download/default/48px.svg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@ -212,7 +230,8 @@
|
|||||||
type="url"
|
type="url"
|
||||||
name="menu_url"
|
name="menu_url"
|
||||||
id="menu_url"
|
id="menu_url"
|
||||||
pattern="https://.*" />
|
pattern="https://.*\.json" />
|
||||||
|
<button class="icon" icon="download" id="download" type="button"></button>
|
||||||
<input
|
<input
|
||||||
required
|
required
|
||||||
autocomplete="new-password"
|
autocomplete="new-password"
|
||||||
|
325
web/main.js
325
web/main.js
@ -1,10 +1,13 @@
|
|||||||
|
let api_url = localStorage.getItem('api_url') ?? '';
|
||||||
|
let menu_url = localStorage.getItem('menu_url') ?? '';
|
||||||
|
let api_token = localStorage.getItem('api_token') ?? '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all entities in HomeAssistant.
|
* Get all entities in HomeAssistant.
|
||||||
* @param {string} api_url
|
|
||||||
* @param {string} api_token
|
|
||||||
* @returns {Promise<Record<string, string>>} [id, name]
|
* @returns {Promise<Record<string, string>>} [id, name]
|
||||||
*/
|
*/
|
||||||
async function get_entities(api_url, api_token) {
|
async function get_entities() {
|
||||||
|
try {
|
||||||
const res = await fetch(api_url + '/template', {
|
const res = await fetch(api_url + '/template', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -15,17 +18,23 @@ async function get_entities(api_url, api_token) {
|
|||||||
});
|
});
|
||||||
if (res.status == 401 || res.status == 403) {
|
if (res.status == 401 || res.status == 403) {
|
||||||
document.querySelector('#api_token').classList.add('invalid');
|
document.querySelector('#api_token').classList.add('invalid');
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
document.querySelector('#api_url').classList.remove('invalid');
|
||||||
|
document.querySelector('#api_token').classList.remove('invalid');
|
||||||
return Object.fromEntries(await res.json());
|
return Object.fromEntries(await res.json());
|
||||||
|
} catch {
|
||||||
|
document.querySelector('#api_url').classList.add('invalid');
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all devices in HomeAssistant.
|
* Get all devices in HomeAssistant.
|
||||||
* @param {string} api_url
|
|
||||||
* @param {string} api_token
|
|
||||||
* @returns {Promise<Record<string, string>>} [id, name]
|
* @returns {Promise<Record<string, string>>} [id, name]
|
||||||
*/
|
*/
|
||||||
async function get_devices(api_url, api_token) {
|
async function get_devices() {
|
||||||
|
try {
|
||||||
const res = await fetch(api_url + '/template', {
|
const res = await fetch(api_url + '/template', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -36,17 +45,23 @@ async function get_devices(api_url, api_token) {
|
|||||||
});
|
});
|
||||||
if (res.status == 401 || res.status == 403) {
|
if (res.status == 401 || res.status == 403) {
|
||||||
document.querySelector('#api_token').classList.add('invalid');
|
document.querySelector('#api_token').classList.add('invalid');
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
document.querySelector('#api_url').classList.remove('invalid');
|
||||||
|
document.querySelector('#api_token').classList.remove('invalid');
|
||||||
return Object.fromEntries(await res.json());
|
return Object.fromEntries(await res.json());
|
||||||
|
} catch {
|
||||||
|
document.querySelector('#api_url').classList.add('invalid');
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all areas in HomeAssistant.
|
* Get all areas in HomeAssistant.
|
||||||
* @param {string} api_url
|
|
||||||
* @param {string} api_token
|
|
||||||
* @returns {Promise<Record<string, string>>} [id, name]
|
* @returns {Promise<Record<string, string>>} [id, name]
|
||||||
*/
|
*/
|
||||||
async function get_areas(api_url, api_token) {
|
async function get_areas() {
|
||||||
|
try {
|
||||||
const res = await fetch(api_url + '/template', {
|
const res = await fetch(api_url + '/template', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -57,17 +72,23 @@ async function get_areas(api_url, api_token) {
|
|||||||
});
|
});
|
||||||
if (res.status == 401 || res.status == 403) {
|
if (res.status == 401 || res.status == 403) {
|
||||||
document.querySelector('#api_token').classList.add('invalid');
|
document.querySelector('#api_token').classList.add('invalid');
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
document.querySelector('#api_url').classList.remove('invalid');
|
||||||
|
document.querySelector('#api_token').classList.remove('invalid');
|
||||||
return Object.fromEntries(await res.json());
|
return Object.fromEntries(await res.json());
|
||||||
|
} catch {
|
||||||
|
document.querySelector('#api_url').classList.add('invalid');
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all services in HomeAssistant.
|
* Get all services in HomeAssistant.
|
||||||
* @param {string} api_url
|
|
||||||
* @param {string} api_token
|
|
||||||
* @returns {Promise<[string, { name: string; description: string; fields: Record<string, { name: string; description: string; example: string; selector: unknown; required?: boolean }> }][]>} [id, data]
|
* @returns {Promise<[string, { name: string; description: string; fields: Record<string, { name: string; description: string; example: string; selector: unknown; required?: boolean }> }][]>} [id, data]
|
||||||
*/
|
*/
|
||||||
async function get_services(api_url, api_token) {
|
async function get_services() {
|
||||||
|
try {
|
||||||
const res = await fetch(api_url + '/services', {
|
const res = await fetch(api_url + '/services', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
@ -77,7 +98,10 @@ async function get_services(api_url, api_token) {
|
|||||||
});
|
});
|
||||||
if (res.status == 401 || res.status == 403) {
|
if (res.status == 401 || res.status == 403) {
|
||||||
document.querySelector('#api_token').classList.add('invalid');
|
document.querySelector('#api_token').classList.add('invalid');
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
document.querySelector('#api_url').classList.remove('invalid');
|
||||||
|
document.querySelector('#api_token').classList.remove('invalid');
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const services = [];
|
const services = [];
|
||||||
for (const d of data) {
|
for (const d of data) {
|
||||||
@ -86,6 +110,10 @@ async function get_services(api_url, api_token) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return services;
|
return services;
|
||||||
|
} catch {
|
||||||
|
document.querySelector('#api_url').classList.add('invalid');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -343,69 +371,6 @@ async function generate_schema(entities, devices, areas, services, schema) {
|
|||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
let api_url = localStorage.getItem('api_url') ?? '';
|
|
||||||
let menu_url = localStorage.getItem('menu_url') ?? '';
|
|
||||||
let api_token = localStorage.getItem('api_token') ?? '';
|
|
||||||
document.querySelector('#api_url').value = api_url;
|
|
||||||
document.querySelector('#menu_url').value = menu_url;
|
|
||||||
document.querySelector('#api_token').value = api_token;
|
|
||||||
|
|
||||||
document.querySelector('#troubleshooting').addEventListener('click', (e) => {
|
|
||||||
document.querySelector('#troubleshooting-dialog').showModal();
|
|
||||||
});
|
|
||||||
|
|
||||||
document.querySelector('#test-api').addEventListener('click', async (e) => {
|
|
||||||
try {
|
|
||||||
document.querySelector('#test-api-response').innerText = 'Testing...';
|
|
||||||
const res = await fetch(api_url + '/', {
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${api_token}`,
|
|
||||||
},
|
|
||||||
cache: 'no-cache',
|
|
||||||
mode: 'cors',
|
|
||||||
});
|
|
||||||
const text = await res.text();
|
|
||||||
if (res.status == 200) {
|
|
||||||
document.querySelector('#test-api-response').innerText =
|
|
||||||
JSON.parse(text).message;
|
|
||||||
} else if (res.status == 400) {
|
|
||||||
try {
|
|
||||||
document.querySelector('#test-api-response').innerText =
|
|
||||||
JSON.parse(text).message;
|
|
||||||
} catch {
|
|
||||||
document.querySelector('#test-api-response').innerText = text;
|
|
||||||
}
|
|
||||||
} else if (res.status == 401 || res.status == 403) {
|
|
||||||
document.querySelector('#api_token').classList.add('invalid');
|
|
||||||
document.querySelector('#test-api-response').innerText = 'Invalid token.';
|
|
||||||
} else {
|
|
||||||
document.querySelector('#test-api-response').innerText = text;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
document.querySelector('#test-api-response').innerText = e.message;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
document.querySelector('#test-menu').addEventListener('click', async (e) => {
|
|
||||||
try {
|
|
||||||
document.querySelector('#test-menu-response').innerText = 'Testing...';
|
|
||||||
const res = await fetch(menu_url, {
|
|
||||||
cache: 'no-cache',
|
|
||||||
mode: 'cors',
|
|
||||||
});
|
|
||||||
if (res.status == 200) {
|
|
||||||
document.querySelector('#test-menu-response').innerText = 'Available';
|
|
||||||
} else if (res.status == 400) {
|
|
||||||
document.querySelector('#test-menu-response').innerText =
|
|
||||||
await res.text();
|
|
||||||
} else {
|
|
||||||
document.querySelector('#test-menu-response').innerText =
|
|
||||||
await res.text();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
document.querySelector('#test-menu-response').innerText = e.message;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function get(d, p) {
|
function get(d, p) {
|
||||||
for (let i = 0; i < p.length; i++) {
|
for (let i = 0; i < p.length; i++) {
|
||||||
d = d[p[i]];
|
d = d[p[i]];
|
||||||
@ -432,6 +397,38 @@ function toast({ text, color }) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let entities, devices, areas, services, schema;
|
||||||
|
async function loadSchema() {
|
||||||
|
[entities, devices, areas, services, schema] = await Promise.all([
|
||||||
|
get_entities(),
|
||||||
|
get_devices(),
|
||||||
|
get_areas(),
|
||||||
|
get_services(),
|
||||||
|
get_schema(),
|
||||||
|
]);
|
||||||
|
if (window.makeMarkers) {
|
||||||
|
window.makeMarkers();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
schema = await generate_schema(entities, devices, areas, services, schema);
|
||||||
|
} catch {}
|
||||||
|
console.log(schema);
|
||||||
|
if (window.m && window.modelUri) {
|
||||||
|
// configure the JSON language support with schemas and schema associations
|
||||||
|
window.m.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||||
|
validate: true,
|
||||||
|
schemas: [
|
||||||
|
{
|
||||||
|
uri: 'https://raw.githubusercontent.com/house-of-abbey/GarminHomeAssistant/main/config.schema.json',
|
||||||
|
fileMatch: [window.modelUri.toString()],
|
||||||
|
schema,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadSchema();
|
||||||
|
|
||||||
// require is provided by loader.min.js.
|
// require is provided by loader.min.js.
|
||||||
require.config({
|
require.config({
|
||||||
paths: {
|
paths: {
|
||||||
@ -439,26 +436,11 @@ require.config({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
require(['vs/editor/editor.main'], async () => {
|
require(['vs/editor/editor.main'], async () => {
|
||||||
let entities, devices, areas, services, schema;
|
window.m = monaco;
|
||||||
async function loadSchema() {
|
var modelUri = monaco.Uri.parse('/config/www/garmin/menu.json'); // a made up unique URI for our model
|
||||||
[entities, devices, areas, services, schema] = await Promise.all([
|
window.modelUri = modelUri;
|
||||||
get_entities(api_url, api_token),
|
|
||||||
get_devices(api_url, api_token),
|
if (schema) {
|
||||||
get_areas(api_url, api_token),
|
|
||||||
get_services(api_url, api_token),
|
|
||||||
get_schema(),
|
|
||||||
]);
|
|
||||||
makeMarkers();
|
|
||||||
try {
|
|
||||||
schema = await generate_schema(
|
|
||||||
entities,
|
|
||||||
devices,
|
|
||||||
areas,
|
|
||||||
services,
|
|
||||||
schema
|
|
||||||
);
|
|
||||||
} catch {}
|
|
||||||
console.log(schema);
|
|
||||||
// configure the JSON language support with schemas and schema associations
|
// configure the JSON language support with schemas and schema associations
|
||||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||||
validate: true,
|
validate: true,
|
||||||
@ -472,6 +454,110 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.querySelector('#api_url').value = api_url;
|
||||||
|
document.querySelector('#menu_url').value = menu_url;
|
||||||
|
document.querySelector('#api_token').value = api_token;
|
||||||
|
|
||||||
|
document.querySelector('#troubleshooting').addEventListener('click', (e) => {
|
||||||
|
document.querySelector('#troubleshooting-dialog').showModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector('#test-api').addEventListener('click', async (e) => {
|
||||||
|
try {
|
||||||
|
document.querySelector('#test-api-response').innerText = 'Testing...';
|
||||||
|
const res = await fetch(api_url + '/', {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${api_token}`,
|
||||||
|
},
|
||||||
|
cache: 'no-cache',
|
||||||
|
mode: 'cors',
|
||||||
|
});
|
||||||
|
const text = await res.text();
|
||||||
|
if (res.status == 200) {
|
||||||
|
document.querySelector('#test-api-response').innerText =
|
||||||
|
JSON.parse(text).message;
|
||||||
|
document.querySelector('#api_token').classList.remove('invalid');
|
||||||
|
document.querySelector('#api_url').classList.remove('invalid');
|
||||||
|
} else if (res.status == 400) {
|
||||||
|
document.querySelector('#api_url').classList.add('invalid');
|
||||||
|
try {
|
||||||
|
document.querySelector('#test-api-response').innerText =
|
||||||
|
JSON.parse(text).message;
|
||||||
|
} catch {
|
||||||
|
document.querySelector('#test-api-response').innerText = text;
|
||||||
|
}
|
||||||
|
} else if (res.status == 401 || res.status == 403) {
|
||||||
|
document.querySelector('#api_token').classList.add('invalid');
|
||||||
|
document.querySelector('#test-api-response').innerText =
|
||||||
|
'Invalid token.';
|
||||||
|
} else {
|
||||||
|
document.querySelector('#test-api-response').innerText = text;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
document.querySelector('#test-api-response').innerText =
|
||||||
|
'Check CORS settings on HomeAssistant server.';
|
||||||
|
document.querySelector('#api_token').classList.add('invalid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.querySelector('#test-menu').addEventListener('click', async (e) => {
|
||||||
|
try {
|
||||||
|
document.querySelector('#test-menu-response').innerText = 'Testing...';
|
||||||
|
const res = await fetch(menu_url, {
|
||||||
|
cache: 'no-cache',
|
||||||
|
mode: 'cors',
|
||||||
|
});
|
||||||
|
if (res.status == 200) {
|
||||||
|
document.querySelector('#menu_url').classList.remove('invalid');
|
||||||
|
document.querySelector('#test-menu-response').innerText = 'Available';
|
||||||
|
} else if (res.status == 400) {
|
||||||
|
document.querySelector('#menu_url').classList.add('invalid');
|
||||||
|
document.querySelector('#test-menu-response').innerText =
|
||||||
|
await res.text();
|
||||||
|
} else {
|
||||||
|
document.querySelector('#menu_url').classList.add('invalid');
|
||||||
|
document.querySelector('#test-menu-response').innerText =
|
||||||
|
await res.text();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
document.querySelector('#menu_url').classList.add('invalid');
|
||||||
|
document.querySelector('#test-menu-response').innerText =
|
||||||
|
'Check CORS settings on HomeAssistant server.';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.querySelector('#download').addEventListener('click', async (e) => {
|
||||||
|
try {
|
||||||
|
const t = toast({
|
||||||
|
text: 'Downloading...',
|
||||||
|
});
|
||||||
|
const res = await fetch(menu_url, {
|
||||||
|
cache: 'no-cache',
|
||||||
|
mode: 'cors',
|
||||||
|
});
|
||||||
|
t.hideToast();
|
||||||
|
if (res.status == 200) {
|
||||||
|
document.querySelector('#menu_url').classList.remove('invalid');
|
||||||
|
const text = await res.text();
|
||||||
|
model.setValue(text);
|
||||||
|
toast({
|
||||||
|
text: 'Downloaded!',
|
||||||
|
color: 'var(--ctp-mocha-green)',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
document.querySelector('#menu_url').classList.add('invalid');
|
||||||
|
toast({
|
||||||
|
text: await res.text(),
|
||||||
|
color: 'var(--ctp-mocha-red)',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
toast({
|
||||||
|
text: 'Check CORS settings on HomeAssistant server.',
|
||||||
|
color: 'var(--ctp-mocha-red)',
|
||||||
|
});
|
||||||
|
document.querySelector('#menu_url').classList.add('invalid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
document.querySelector('#api_url').addEventListener('change', (e) => {
|
document.querySelector('#api_url').addEventListener('change', (e) => {
|
||||||
api_url = e.target.value;
|
api_url = e.target.value;
|
||||||
localStorage.setItem('api_url', api_url);
|
localStorage.setItem('api_url', api_url);
|
||||||
@ -491,17 +577,18 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
document.querySelector('#test-api-response').innerText = 'Check now!';
|
document.querySelector('#test-api-response').innerText = 'Check now!';
|
||||||
loadSchema();
|
loadSchema();
|
||||||
});
|
});
|
||||||
loadSchema();
|
|
||||||
checkRemoteMenu();
|
checkRemoteMenu();
|
||||||
|
|
||||||
async function checkRemoteMenu() {
|
async function checkRemoteMenu() {
|
||||||
if (menu_url != '') {
|
if (menu_url != '') {
|
||||||
|
try {
|
||||||
const remote = await fetch(menu_url, {
|
const remote = await fetch(menu_url, {
|
||||||
cache: 'no-cache',
|
cache: 'no-cache',
|
||||||
mode: 'cors',
|
mode: 'cors',
|
||||||
});
|
});
|
||||||
if (remote.status == 200) {
|
if (remote.status == 200) {
|
||||||
document.querySelector('#menu_url').classList.remove('invalid');
|
document.querySelector('#menu_url').classList.remove('invalid');
|
||||||
|
document.querySelector('#download').disabled = false;
|
||||||
const text = await remote.text();
|
const text = await remote.text();
|
||||||
if (model.getValue() === text) {
|
if (model.getValue() === text) {
|
||||||
document.querySelector('#menu_url').classList.remove('outofsync');
|
document.querySelector('#menu_url').classList.remove('outofsync');
|
||||||
@ -510,13 +597,20 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
document.querySelector('#menu_url').classList.add('invalid');
|
document.querySelector('#menu_url').classList.add('invalid');
|
||||||
|
document.querySelector('#download').disabled = true;
|
||||||
}
|
}
|
||||||
|
} catch {
|
||||||
|
document.querySelector('#menu_url').classList.add('invalid');
|
||||||
|
document.querySelector('#download').disabled = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
document.querySelector('#menu_url').classList.remove('invalid');
|
||||||
|
document.querySelector('#download').disabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configures two JSON schemas, with references.
|
setInterval(checkRemoteMenu, 30000);
|
||||||
|
|
||||||
var modelUri = monaco.Uri.parse('/config/www/garmin/menu.json'); // a made up unique URI for our model
|
|
||||||
var model = monaco.editor.createModel(
|
var model = monaco.editor.createModel(
|
||||||
localStorage.getItem('json') ?? '{}',
|
localStorage.getItem('json') ?? '{}',
|
||||||
'json',
|
'json',
|
||||||
@ -556,6 +650,7 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
const t = toast({
|
const t = toast({
|
||||||
text: 'Rendering template...',
|
text: 'Rendering template...',
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
const res = await fetch(api_url + '/template', {
|
const res = await fetch(api_url + '/template', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -583,6 +678,14 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
color: 'var(--ctp-mocha-red)',
|
color: 'var(--ctp-mocha-red)',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
t.hideToast();
|
||||||
|
toast({
|
||||||
|
text: 'Check CORS settings on HomeAssistant server.',
|
||||||
|
color: 'var(--ctp-mocha-red)',
|
||||||
|
});
|
||||||
|
document.querySelector('#api_url').classList.add('invalid');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
@ -602,6 +705,7 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
const t = toast({
|
const t = toast({
|
||||||
text: 'Running action...',
|
text: 'Running action...',
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
api_url + '/services/' + service[0] + '/' + service[1],
|
api_url + '/services/' + service[0] + '/' + service[1],
|
||||||
{
|
{
|
||||||
@ -641,6 +745,14 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
makeMarkers();
|
makeMarkers();
|
||||||
|
} catch (e) {
|
||||||
|
t.hideToast();
|
||||||
|
toast({
|
||||||
|
text: 'Check CORS settings on HomeAssistant server.',
|
||||||
|
color: 'var(--ctp-mocha-red)',
|
||||||
|
});
|
||||||
|
document.querySelector('#api_url').classList.add('invalid');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
@ -652,7 +764,10 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
const t = toast({
|
const t = toast({
|
||||||
text: 'Toggling...',
|
text: 'Toggling...',
|
||||||
});
|
});
|
||||||
const res = await fetch(api_url + '/services/' + entity[0] + '/toggle', {
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
api_url + '/services/' + entity[0] + '/toggle',
|
||||||
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${api_token}`,
|
Authorization: `Bearer ${api_token}`,
|
||||||
@ -661,7 +776,8 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
entity_id: item.entity,
|
entity_id: item.entity,
|
||||||
}),
|
}),
|
||||||
});
|
}
|
||||||
|
);
|
||||||
t.hideToast();
|
t.hideToast();
|
||||||
if (res.status == 200) {
|
if (res.status == 200) {
|
||||||
toast({
|
toast({
|
||||||
@ -690,6 +806,14 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
makeMarkers();
|
makeMarkers();
|
||||||
|
} catch (e) {
|
||||||
|
t.hideToast();
|
||||||
|
toast({
|
||||||
|
text: 'Check CORS settings on HomeAssistant server.',
|
||||||
|
color: 'var(--ctp-mocha-red)',
|
||||||
|
});
|
||||||
|
document.querySelector('#api_url').classList.add('invalid');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
@ -854,6 +978,7 @@ require(['vs/editor/editor.main'], async () => {
|
|||||||
monaco.editor.setModelMarkers(model, 'template', markers);
|
monaco.editor.setModelMarkers(model, 'template', markers);
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
window.makeMarkers = makeMarkers;
|
||||||
makeMarkers();
|
makeMarkers();
|
||||||
|
|
||||||
model.onDidChangeContent(async function () {
|
model.onDidChangeContent(async function () {
|
||||||
|
Reference in New Issue
Block a user