import { LitElement, css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { Signal, SignalWatcher } from '@lit-labs/signals';
import { getSignal, State, doFetch } from './utils';
import { map } from 'lit/directives/map.js';
import { batchedEffect } from 'signal-utils/subtle/batched-effect';
/**
* Fetch data from a URL and store it in a signal.
*/
@customElement('admin-fetch')
export default class AdminFetch extends SignalWatcher(LitElement) {
/**
* URL to fetch data from.
*/
@property()
url: string = '';
/**
* Signal name of a counter to be notified on a successful fetch.
*/
@property()
emit: string = '';
/**
* Signal name of a counter to trigger a fetch.
*/
@property()
trigger: string = '';
/**
* Signal name of the fetched data.
*/
@property()
data: string = '';
/**
* Signal name of the state of the fetch.
*/
@property()
state: string = '';
/**
* Time interval to fetch data [milliseconds].
*/
@property()
interval: number = -1;
/**
* Number of lines to display in the loading panel.
*/
@property()
lines: number = 3;
@property({
attribute: 'line-min',
})
lineMin: number = 0;
@property({
attribute: 'line-max',
})
lineMax: number = 100;
emitSignal?: Signal.State;
triggerSignal?: Signal.State;
dataSignal?: Signal.State;
stateSignal?: Signal.State;
lastTrigger: number = 0;
linesLength: number[] = [];
connectedCallback() {
super.connectedCallback();
if (!this.url) {
throw new Error('url is required');
}
this.emitSignal = getSignal(this.emit);
this.emitSignal.set(0);
this.triggerSignal = getSignal(this.trigger);
this.triggerSignal.set(this.lastTrigger);
this.dataSignal = getSignal(this.data);
this.stateSignal = getSignal(this.state);
this.stateSignal.set(State.Loading);
this.linesLength = Array.from({ length: this.lines }, () => {
return Math.floor(Math.random() * (this.lineMax - this.lineMin) + this.lineMin);
});
console.log(this.linesLength);
doFetch(this.url, this.dataSignal, this.emitSignal, this.stateSignal);
batchedEffect(() => {
if (this.triggerSignal?.get() === this.lastTrigger) {
return;
}
this.lastTrigger = this.triggerSignal?.get() ?? 0;
if (this.stateSignal) {
if (this.stateSignal.get() === State.Loading || this.stateSignal.get() === State.Reloading) {
return;
}
this.stateSignal.set(State.Reloading);
}
if (this.dataSignal && this.emitSignal) {
doFetch(this.url, this.dataSignal, this.emitSignal, this.stateSignal);
}
});
if (this.interval > 0) {
setInterval(() => {
if (this.stateSignal) {
this.stateSignal.set(State.Reloading);
}
if (this.dataSignal && this.emitSignal) {
doFetch(this.url, this.dataSignal, this.emitSignal, this.stateSignal);
}
}, this.interval);
}
}
static styles = css`
.placeholder {
min-height: 1em;
vertical-align: middle;
cursor: wait;
background-color: currentcolor;
opacity: 0.5;
margin-block-start: 0.3em;
margin-block-end: 0.3em;
}
`;
render() {
if (this.stateSignal?.get() === State.Error) {
return html`Error
`;
}
if (this.stateSignal?.get() === State.Loading) {
return map(
this.linesLength,
(length) => html``,
);
}
return html``;
}
}