mirror of
https://github.com/1f349/admin.1f349.com.git
synced 2024-11-12 22:51:35 +00:00
Add string based sorting and fix issues with target management views
This commit is contained in:
parent
6adc2b11cc
commit
9b72a57ff0
@ -28,6 +28,10 @@ export class RestTable<T extends object> implements IPromiseLike<RestTable<T>> {
|
||||
return this.errorReason;
|
||||
}
|
||||
|
||||
makeItem(x: T): RestItem<T> {
|
||||
return new RestItem(this, x);
|
||||
}
|
||||
|
||||
reload() {
|
||||
(async () => {
|
||||
try {
|
||||
@ -37,7 +41,7 @@ export class RestTable<T extends object> implements IPromiseLike<RestTable<T>> {
|
||||
if (f.status != 200) throw new Error("Unexpected status code: " + f.status);
|
||||
let fJson = await f.json();
|
||||
let rows = fJson as T[];
|
||||
this.rows = rows.map(x => new RestItem(this, x));
|
||||
this.rows = rows.map(x => this.makeItem(x));
|
||||
this.loading = false;
|
||||
this.updateSubs();
|
||||
} catch (err) {
|
||||
@ -82,10 +86,25 @@ export class RestItem<T extends object> implements IPromiseLike<RestItem<T>> {
|
||||
this.subs.forEach(x => x(this));
|
||||
}
|
||||
|
||||
setLoading(loading: boolean) {
|
||||
this.loading = loading;
|
||||
this.updateSubs();
|
||||
}
|
||||
|
||||
setErrorReason(errorReason: string) {
|
||||
this.errorReason = errorReason;
|
||||
}
|
||||
|
||||
key(): string {
|
||||
return this.table.keyFunc(this.data);
|
||||
}
|
||||
|
||||
keyUrl(): string {
|
||||
let keyPath = "/" + this.key();
|
||||
if (keyPath === "/") keyPath = "";
|
||||
return this.table.apiUrl + keyPath;
|
||||
}
|
||||
|
||||
isLoading(): boolean {
|
||||
return this.loading;
|
||||
}
|
||||
@ -94,40 +113,36 @@ export class RestItem<T extends object> implements IPromiseLike<RestItem<T>> {
|
||||
return this.errorReason;
|
||||
}
|
||||
|
||||
update(data: T): Promise<void> {
|
||||
this.loading = true;
|
||||
this.updateSubs();
|
||||
return LOGIN.clientRequest(this.table.apiUrl + "/" + this.key(), {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(this.data),
|
||||
})
|
||||
.then(x => {
|
||||
if (x.status !== 200) throw new Error("Unexpected status code: " + x.status);
|
||||
this.data = data;
|
||||
this.loading = false;
|
||||
this.updateSubs();
|
||||
})
|
||||
.catch(x => {
|
||||
this.loading = false;
|
||||
this.updateSubs();
|
||||
});
|
||||
async update(data: T, options?: RequestInit): Promise<void> {
|
||||
this.setLoading(true);
|
||||
if (!options)
|
||||
options = {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(this.data),
|
||||
};
|
||||
try {
|
||||
const x = await LOGIN.clientRequest(this.keyUrl(), options);
|
||||
if (x.status !== 200) throw new Error("Unexpected status code: " + x.status);
|
||||
this.data = data;
|
||||
this.setLoading(false);
|
||||
} catch (err) {
|
||||
this.setErrorReason("Failed to update item " + this.key());
|
||||
this.setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
remove(): Promise<void> {
|
||||
this.loading = true;
|
||||
this.updateSubs();
|
||||
return LOGIN.clientRequest(this.table.apiUrl + "/" + this.key(), {method: "DELETE"})
|
||||
.then(x => {
|
||||
if (x.status !== 200) throw new Error("Unexpected status code: " + x.status);
|
||||
this.table.rows = this.table.rows.filter(x => this.table.keyFunc(x.data) !== this.key());
|
||||
this.loading = false;
|
||||
this.updateSubs();
|
||||
})
|
||||
.catch(x => {
|
||||
this.errorReason = "Failed to remove item " + this.table.keyFunc(this.data);
|
||||
this.loading = false;
|
||||
this.updateSubs();
|
||||
});
|
||||
async remove(options?: RequestInit): Promise<void> {
|
||||
this.setLoading(true);
|
||||
if (!options) options = {method: "DELETE"};
|
||||
try {
|
||||
const x = await LOGIN.clientRequest(this.keyUrl(), options);
|
||||
if (x.status !== 200) throw new Error("Unexpected status code: " + x.status);
|
||||
this.table.rows = this.table.rows.filter(x_1 => this.table.keyFunc(x_1.data) !== this.key());
|
||||
this.setLoading(false);
|
||||
} catch (err) {
|
||||
this.setErrorReason("Failed to remove item " + this.key());
|
||||
this.setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(run: Subscriber<RestItem<T>>): Unsubscriber {
|
||||
|
29
src/utils/target-table.ts
Normal file
29
src/utils/target-table.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import {RestItem, RestTable} from "./rest-table";
|
||||
|
||||
interface Target {
|
||||
src: string;
|
||||
}
|
||||
|
||||
export class TargetTable<T extends Target> extends RestTable<T> {
|
||||
constructor(apiUrl: string, keyFunc: (item: T) => string) {
|
||||
super(apiUrl, keyFunc);
|
||||
}
|
||||
|
||||
makeItem(x: T): RestItem<T> {
|
||||
return new TargetItem(this, x);
|
||||
}
|
||||
}
|
||||
|
||||
export class TargetItem<T extends Target> extends RestItem<T> {
|
||||
constructor(table: TargetTable<T>, data: T) {
|
||||
super(table, data);
|
||||
}
|
||||
|
||||
update(data: T): Promise<void> {
|
||||
return super.update(data, {method: "POST", body: JSON.stringify({...data, src: data.src})});
|
||||
}
|
||||
|
||||
remove(): Promise<void> {
|
||||
return super.remove({method: "DELETE", body: JSON.stringify({src: this.data.src})});
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
<script lang="ts">
|
||||
import PromiseLike from "../components/PromiseLike.svelte";
|
||||
import PromiseTable from "../components/PromiseTable.svelte";
|
||||
import X from "../icons/X.svelte";
|
||||
import {domainOption} from "../stores/domain-option";
|
||||
import {LOGIN} from "../utils/login";
|
||||
import {RestItem, RestTable} from "../utils/rest-table";
|
||||
|
||||
const apiOrchid = import.meta.env.VITE_API_ORCHID;
|
||||
|
@ -15,8 +15,8 @@
|
||||
branches: string[];
|
||||
}
|
||||
|
||||
function rowsDomainFilter(rows: RestItem<Site>[], domain: string): RestItem<Site>[] {
|
||||
return rows.filter(x => domainFilter(x.data.domain, domain));
|
||||
function rowOrdering(rows: RestItem<Site>[], domain: string): RestItem<Site>[] {
|
||||
return rows.filter(x => domainFilter(x.data.domain, domain)).sort((a, b) => a.data.domain.localeCompare(b.data.domain));
|
||||
}
|
||||
|
||||
function domainFilter(src: string, domain: string) {
|
||||
@ -64,7 +64,7 @@
|
||||
</tr>
|
||||
|
||||
<svelte:fragment slot="rows" let:value>
|
||||
{#each rowsDomainFilter(value.rows, $domainOption) as item}
|
||||
{#each rowOrdering(value.rows, $domainOption) as item}
|
||||
<PromiseLike value={item}>
|
||||
<tr slot="loading" class="empty-row">
|
||||
<td colspan="100">
|
||||
@ -105,7 +105,6 @@
|
||||
grid-template-columns: repeat(2, auto);
|
||||
justify-content: left;
|
||||
align-content: center;
|
||||
gap: 8px;
|
||||
|
||||
div a {
|
||||
display: block;
|
||||
|
@ -5,8 +5,10 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import {TargetTable} from "../utils/target-table";
|
||||
|
||||
import {domainOption} from "../stores/domain-option";
|
||||
import {RestItem, RestTable} from "../utils/rest-table";
|
||||
import {RestItem} from "../utils/rest-table";
|
||||
import PromiseTable from "../components/PromiseTable.svelte";
|
||||
import PromiseLike from "../components/PromiseLike.svelte";
|
||||
|
||||
@ -14,10 +16,10 @@
|
||||
|
||||
export let apiUrl: string;
|
||||
|
||||
let table = new RestTable<T>(apiUrl, (item: T) => item.src);
|
||||
let table = new TargetTable<T>(apiUrl, (item: T) => item.src);
|
||||
|
||||
function rowsDomainFilter(rows: RestItem<T>[], domain: string): RestItem<T>[] {
|
||||
return rows.filter(x => domainFilter(x.data, domain));
|
||||
function rowOrdering(rows: RestItem<T>[], domain: string): RestItem<T>[] {
|
||||
return rows.filter(x => domainFilter(x.data, domain)).sort((a, b) => a.data.src.localeCompare(b.data.src));
|
||||
}
|
||||
|
||||
function domainFilter(item: T, domain: string): boolean {
|
||||
@ -41,7 +43,7 @@
|
||||
</tr>
|
||||
|
||||
<svelte:fragment slot="rows" let:value>
|
||||
{#each rowsDomainFilter(value.rows, $domainOption) as item}
|
||||
{#each rowOrdering(value.rows, $domainOption) as item}
|
||||
<PromiseLike value={item}>
|
||||
<tr slot="loading" class="empty-row">
|
||||
<td colspan="100">
|
||||
|
Loading…
Reference in New Issue
Block a user