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