refactor(static): split schedule and weather to modules

This commit is contained in:
2026-09-07 18:09:49 +03:00
parent d44c8076b4
commit 5db61da32b
7 changed files with 124 additions and 117 deletions
+41
View File
@@ -0,0 +1,41 @@
export class DataStorage<T extends { id: string }> {
constructor(private storageKey: string) {}
private readValues(): T[] {
const objects = JSON.parse(window.localStorage.getItem(this.storageKey) || "[]");
if (!Array.isArray(objects)) {
return Object.values(objects);
}
return objects;
}
private writeValues(values: T[]) {
window.localStorage.setItem(this.storageKey, JSON.stringify(values));
}
getAll(): T[] {
return this.readValues();
}
add(value: T) {
const values = this.readValues();
for (const v of values) {
if (v.id == value.id) {
return;
}
}
values.push(value);
this.writeValues(values);
}
remove(id: string) {
const values = this.readValues();
for (let i = 0; i < values.length; i++) {
if (values[i].id == id) {
values.splice(i, 1);
this.writeValues(values);
return;
}
}
}
}
@@ -1,50 +1,6 @@
export interface Channel {
id: string;
name: string;
provider: string;
}
import { Channel } from "./model";
export class ScheduleChannelStorage {
private storageKey: string = "schedule:channels";
getAll(): Channel[] {
const objects = JSON.parse(window.localStorage.getItem(this.storageKey) || "{}");
return Object.values(objects);
}
add(object: Channel) {
const objects = JSON.parse(window.localStorage.getItem(this.storageKey) || "{}");
objects[object.id] = object;
window.localStorage.setItem(this.storageKey, JSON.stringify(objects));
}
remove(id: string) {
const objects = JSON.parse(window.localStorage.getItem(this.storageKey) || "{}");
delete objects[id];
window.localStorage.setItem(this.storageKey, JSON.stringify(objects));
}
}
export class ScheduleChannelManager {
loadChannels(selector: string) {
const channels = window.scheduleChannelStorage.getAll();
const container = document.querySelector(selector);
if (container) {
container.innerHTML = "";
for (const channel of channels) {
const element = new ScheduleChannelElement();
element.setAttribute("channel", JSON.stringify(channel));
element.setAttribute("removable", "");
container.appendChild(element);
}
const groupElement = new ScheduleChannelGroupElement();
groupElement.setAttribute("channels", JSON.stringify(channels));
container.append(groupElement);
}
}
}
class ScheduleChannelElement extends HTMLElement {
export class ScheduleChannelElement extends HTMLElement {
static observedAttributes = ["channel", "removable"];
channel: Channel | null = null;
@@ -100,9 +56,7 @@ class ScheduleChannelElement extends HTMLElement {
}
}
customElements.define("schedule-channel", ScheduleChannelElement);
class ScheduleChannelGroupElement extends HTMLElement {
export class ScheduleChannelGroupElement extends HTMLElement {
static observedAttributes = ["channels"];
channels: Channel[] | null = null;
@@ -124,14 +78,6 @@ class ScheduleChannelGroupElement extends HTMLElement {
this.classList = "list-group-item list-group-item-action";
}
}
customElements.define("schedule-channel", ScheduleChannelElement);
customElements.define("schedule-channel-group", ScheduleChannelGroupElement);
declare global {
interface Window {
scheduleChannelStorage: ScheduleChannelStorage;
scheduleChannelManager: ScheduleChannelManager;
}
}
window.scheduleChannelStorage = new ScheduleChannelStorage();
window.scheduleChannelManager = new ScheduleChannelManager();
+32
View File
@@ -0,0 +1,32 @@
import { DataStorage } from "../base/storage";
import { ScheduleChannelElement, ScheduleChannelGroupElement } from "./component";
import { Channel } from "./model";
export class ScheduleChannelManager {
loadChannels(selector: string) {
const channels = window.scheduleChannelStorage.getAll();
const container = document.querySelector(selector);
if (container) {
container.innerHTML = "";
for (const channel of channels) {
const element = new ScheduleChannelElement();
element.setAttribute("channel", JSON.stringify(channel));
element.setAttribute("removable", "");
container.appendChild(element);
}
const groupElement = new ScheduleChannelGroupElement();
groupElement.setAttribute("channels", JSON.stringify(channels));
container.append(groupElement);
}
}
}
declare global {
interface Window {
scheduleChannelStorage: DataStorage<Channel>;
scheduleChannelManager: ScheduleChannelManager;
}
}
window.scheduleChannelStorage = new DataStorage("schedule:channels");
window.scheduleChannelManager = new ScheduleChannelManager();
+5
View File
@@ -0,0 +1,5 @@
export interface Channel {
id: string;
name: string;
provider: string;
}
@@ -1,51 +1,6 @@
export interface Location {
id: string;
name: string;
provider: string;
country_code: string;
country?: string;
district?: string;
subdistrict?: string;
}
import { Location } from "./model";
export class WeatherLocationStorage {
private storageKey: string = "weather:locations";
getAll(): Location[] {
const locations = JSON.parse(window.localStorage.getItem(this.storageKey) || "{}");
return Object.values(locations);
}
add(location: Location) {
const locations = JSON.parse(window.localStorage.getItem(this.storageKey) || "{}");
locations[location.id] = location;
window.localStorage.setItem(this.storageKey, JSON.stringify(locations));
}
remove(id: string) {
const locations = JSON.parse(window.localStorage.getItem(this.storageKey) || "{}");
delete locations[id];
window.localStorage.setItem(this.storageKey, JSON.stringify(locations));
}
}
export class WeatherLocationManager {
loadLocations(selector: string) {
const locations = window.weatherLocationStorage.getAll();
const container = document.querySelector(selector);
if (container) {
container.innerHTML = "";
for (const location of locations) {
const element = new WeatherLocationElement();
element.setAttribute("location", JSON.stringify(location));
element.setAttribute("removable", "");
container.appendChild(element);
}
}
}
}
class WeatherLocationElement extends HTMLElement {
export class WeatherLocationElement extends HTMLElement {
static observedAttributes = ["location", "removable"];
location: Location | null = null;
@@ -75,7 +30,7 @@ class WeatherLocationElement extends HTMLElement {
</span>
</span>
</a>`;
this.classList = 'list-group-item list-group-item-action';
this.classList = "list-group-item list-group-item-action";
this.addEventListener("click", this.handleClick);
if (this.hasAttribute("removable")) {
this.querySelector<HTMLElement>("[data-remove]")?.addEventListener("click", this.handleRemoveClick);
@@ -106,13 +61,3 @@ class WeatherLocationElement extends HTMLElement {
}
customElements.define("weather-location", WeatherLocationElement);
declare global {
interface Window {
weatherLocationStorage: WeatherLocationStorage;
weatherLocationManager: WeatherLocationManager;
}
}
window.weatherLocationStorage = new WeatherLocationStorage();
window.weatherLocationManager = new WeatherLocationManager();
+29
View File
@@ -0,0 +1,29 @@
import { DataStorage } from "../base/storage";
import { WeatherLocationElement } from "./component";
import { Location } from "./model";
export class WeatherLocationManager {
loadLocations(selector: string) {
const locations = window.weatherLocationStorage.getAll();
const container = document.querySelector(selector);
if (container) {
container.innerHTML = "";
for (const location of locations) {
const element = new WeatherLocationElement();
element.setAttribute("location", JSON.stringify(location));
element.setAttribute("removable", "");
container.appendChild(element);
}
}
}
}
declare global {
interface Window {
weatherLocationStorage: DataStorage<Location>;
weatherLocationManager: WeatherLocationManager;
}
}
window.weatherLocationStorage = new DataStorage("weather:locations");
window.weatherLocationManager = new WeatherLocationManager();
+9
View File
@@ -0,0 +1,9 @@
export interface Location {
id: string;
name: string;
provider: string;
country_code: string;
country?: string;
district?: string;
subdistrict?: string;
}