Page MenuHomeSealhub

item.ts
No OneTemporary

import axios from "axios";
import { useState, useEffect } from "./react-api/api";
import EventEmitter from "eventemitter3";
import {
SealiousItem,
SealiousSingleResourceResponse,
SingleResourceParams,
} from "./types";
import url from "./url";
export type ExtractItemFields<
ItemClass extends CollectionItem<any>
> = ItemClass["fields"];
export function useItem<
ItemClass extends CollectionItem<ExtractItemFields<ItemClass>>
>(
itemConstructor: new (id: string) => ItemClass,
id: string
): [boolean, ExtractItemFields<ItemClass> | undefined, ItemClass] {
const [item, setItem] = useState<ItemClass>(() => new itemConstructor(id));
const [data, setData] = useState<ExtractItemFields<ItemClass>>(
{} as ExtractItemFields<ItemClass>
);
useEffect(() => {
item.refresh();
item.on("change", () => {
setData({ ...item.getData() });
setItem(item);
});
}, []);
return [item.loaded, data, item];
}
export abstract class CollectionItem<ItemFields> extends EventEmitter {
collection_name: string;
original_data: ItemFields & SealiousItem;
temp_data: ItemFields;
needs_saving = false;
loaded: boolean;
id: string;
attachments: { [id: string]: SealiousItem } | null;
fields: ItemFields;
writable_fields: Array<keyof ItemFields>;
fields_with_attachments: Array<keyof ItemFields>;
constructor(
id: string,
item?: ItemFields & SealiousItem,
attachments?: { [id: string]: SealiousItem }
) {
super();
this.loaded = false;
this.id = id;
const {
writable_fields,
fields_with_attachments,
fields,
collection_name,
} = this.getInfo();
this.fields = fields;
this.writable_fields = writable_fields;
this.fields_with_attachments = fields_with_attachments;
this.collection_name = collection_name;
if (item) {
this.parseResponse(item, attachments);
}
for (const method of this.getInfo()?.bound_methods || []) {
(this as any)[method] = ((this as any)[method] as Function).bind(
this
);
}
}
abstract getInfo(): {
collection_name: string;
fields: ItemFields;
writable_fields: Array<keyof ItemFields>;
fields_with_attachments: Array<keyof ItemFields>;
bound_methods?: string[];
};
parseResponse(
item: ItemFields & SealiousItem,
attachments?: { [id: string]: SealiousItem }
) {
this.temp_data = { ...item }; // in the future, immutables could prove valuable here
this.original_data = { ...item };
this.attachments = attachments || null;
this.loaded = true;
this.emit("change");
}
getAttachment(id: string) {
return this.attachments?.[id];
}
getURL() {
return `/api/v1/collections/${this.collection_name}/${this.id}`;
}
async refresh(with_attachments = false) {
const params: SingleResourceParams<ItemFields> = {};
if (with_attachments) {
params.attachments = {};
for (const field_name of this.fields_with_attachments) {
params.attachments[field_name] = true;
}
}
const { data: response } = (await axios.get(
url(this.getURL(), params)
)) as {
data: SealiousSingleResourceResponse<ItemFields & SealiousItem>;
};
this.needs_saving = false;
this.parseResponse(response.item, response.attachments);
this.emit("change");
}
getData() {
return this.temp_data;
}
save() {
const payload: Partial<ItemFields> = {};
for (const field of this.writable_fields) {
payload[field] = this.temp_data[field];
}
this.update(payload);
}
setTemp<Field extends keyof ItemFields>(
field: Field,
value: ItemFields[Field]
) {
this.needs_saving = true;
this.temp_data = { ...this.temp_data, [field]: value };
this.emit("change");
this.emit("temp-change");
}
async update(new_values: Partial<ItemFields>) {
await axios.patch(this.getURL(), new_values);
await this.refresh();
}
async delete() {
await axios.delete(this.getURL());
this.emit("change");
}
}

File Metadata

Mime Type
text/x-java
Expires
Sat, Nov 23, 05:39 (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
547875
Default Alt Text
item.ts (3 KB)

Event Timeline