2025-10-13 16:05:50 +02:00
|
|
|
<script lang="ts">
|
|
|
|
import { run, preventDefault } from 'svelte/legacy';
|
2022-03-14 23:12:59 +01:00
|
|
|
import { createEventDispatcher } from "svelte";
|
2025-03-28 14:16:20 +01:00
|
|
|
import { formatDate } from "util/Formatting";
|
2025-03-27 15:38:59 +01:00
|
|
|
import Modal from "util/Modal.svelte"
|
2025-04-02 15:12:38 +02:00
|
|
|
import SortButton from "layout/SortButton.svelte";
|
2024-09-24 00:31:56 +02:00
|
|
|
import { flip } from "svelte/animate";
|
|
|
|
|
|
|
|
const dispatch = createEventDispatcher()
|
2022-03-14 23:12:59 +01:00
|
|
|
|
2025-10-13 16:05:50 +02:00
|
|
|
let { reporters = $bindable([]) } = $props();
|
2024-09-23 19:47:46 +02:00
|
|
|
|
2024-09-24 00:31:56 +02:00
|
|
|
const update_table = (reporters) => sort("")
|
|
|
|
|
2025-10-13 16:05:50 +02:00
|
|
|
let sort_field = $state("last_used")
|
|
|
|
let asc = $state(false)
|
2024-09-24 00:31:56 +02:00
|
|
|
const sort = (field) => {
|
|
|
|
if (field !== "" && field === sort_field) asc = !asc
|
|
|
|
if (field === "") field = sort_field
|
|
|
|
sort_field = field
|
|
|
|
|
|
|
|
console.log("sorting by", field, "asc", asc)
|
|
|
|
reporters.sort((a, b) => {
|
|
|
|
if (typeof (a[field]) === "number") {
|
|
|
|
// Sort ints from high to low
|
|
|
|
if (asc) {
|
|
|
|
return a[field] - b[field]
|
|
|
|
} else {
|
|
|
|
return b[field] - a[field]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Sort strings alphabetically
|
|
|
|
if (asc) {
|
|
|
|
return a[field].localeCompare(b[field])
|
|
|
|
} else {
|
|
|
|
return b[field].localeCompare(a[field])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
reporters = reporters
|
|
|
|
}
|
|
|
|
|
2025-10-13 16:05:50 +02:00
|
|
|
let modal: Modal = $state()
|
|
|
|
let preview_subject = $state("")
|
|
|
|
let preview_html = $state("")
|
|
|
|
let preview_text = $state("")
|
2024-09-23 19:47:46 +02:00
|
|
|
const toggle_preview = (rep) => {
|
|
|
|
preview_subject = rep.last_message_subject
|
|
|
|
preview_text = rep.last_message_text
|
|
|
|
preview_html = rep.last_message_html
|
|
|
|
modal.show()
|
|
|
|
}
|
2025-10-13 16:05:50 +02:00
|
|
|
run(() => {
|
|
|
|
update_table(reporters)
|
|
|
|
});
|
2022-03-14 23:12:59 +01:00
|
|
|
</script>
|
|
|
|
|
2024-09-24 22:46:45 +02:00
|
|
|
<div class="table_scroll">
|
|
|
|
<table>
|
2024-11-06 19:12:52 +01:00
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<td><SortButton field="from_address" active_field={sort_field} asc={asc} sort_func={sort}>Address</SortButton></td>
|
|
|
|
<td><SortButton field="name" active_field={sort_field} asc={asc} sort_func={sort}>Name</SortButton></td>
|
|
|
|
<td><SortButton field="reports_sent" active_field={sort_field} asc={asc} sort_func={sort}>Reports</SortButton></td>
|
|
|
|
<td><SortButton field="files_blocked" active_field={sort_field} asc={asc} sort_func={sort}>Blocked</SortButton></td>
|
|
|
|
<td><SortButton field="last_used" active_field={sort_field} asc={asc} sort_func={sort}>Last used</SortButton></td>
|
|
|
|
<td><SortButton field="created" active_field={sort_field} asc={asc} sort_func={sort}>Created</SortButton></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{#each reporters as rep (rep.from_address)}
|
|
|
|
<tr animate:flip={{duration: 500}}>
|
|
|
|
<td>{rep.from_address}</td>
|
|
|
|
<td>{rep.name}</td>
|
|
|
|
<td>{rep.reports_sent}</td>
|
|
|
|
<td>{rep.files_blocked}</td>
|
|
|
|
<td>{formatDate(rep.last_used, true, true, false)}</td>
|
|
|
|
<td>{formatDate(rep.created, false, false, false)}</td>
|
|
|
|
<td>
|
2025-10-13 16:05:50 +02:00
|
|
|
<button onclick={preventDefault(() => toggle_preview(rep))} class="button round">
|
2024-11-06 19:12:52 +01:00
|
|
|
<i class="icon">email</i>
|
2024-09-24 22:46:45 +02:00
|
|
|
</button>
|
2025-10-13 16:05:50 +02:00
|
|
|
<button onclick={preventDefault(() => {dispatch("edit", rep)})} class="button round">
|
2024-11-06 19:12:52 +01:00
|
|
|
<i class="icon">edit</i>
|
2024-09-24 22:46:45 +02:00
|
|
|
</button>
|
2024-11-06 19:12:52 +01:00
|
|
|
{#if rep.status !== "trusted"}
|
2025-10-13 16:05:50 +02:00
|
|
|
<button onclick={preventDefault(() => {dispatch("approve", rep)})} class="button button_highlight round">
|
2024-11-06 19:12:52 +01:00
|
|
|
<i class="icon">check</i>
|
|
|
|
</button>
|
|
|
|
{/if}
|
|
|
|
{#if rep.status !== "rejected"}
|
2025-10-13 16:05:50 +02:00
|
|
|
<button onclick={preventDefault(() => {dispatch("spam", rep)})} class="button button_red round">
|
2024-11-06 19:12:52 +01:00
|
|
|
<i class="icon">block</i>
|
|
|
|
</button>
|
|
|
|
{/if}
|
2025-10-13 16:05:50 +02:00
|
|
|
<button onclick={preventDefault(() => {dispatch("delete", rep)})} class="button button_red round">
|
2024-11-06 19:12:52 +01:00
|
|
|
<i class="icon">delete</i>
|
|
|
|
</button>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{/each}
|
|
|
|
</tbody>
|
2024-09-24 22:46:45 +02:00
|
|
|
</table>
|
|
|
|
</div>
|
2024-09-23 19:47:46 +02:00
|
|
|
|
|
|
|
<Modal bind:this={modal} title={preview_subject} width="1000px">
|
|
|
|
{#if preview_html !== ""}
|
|
|
|
<div class="message_html">{@html preview_html}</div>
|
|
|
|
{:else if preview_text !== ""}
|
|
|
|
<div class="message_pre">{preview_text}</div>
|
|
|
|
{/if}
|
|
|
|
</Modal>
|
|
|
|
|
|
|
|
<style>
|
2024-09-24 22:46:45 +02:00
|
|
|
.table_scroll {
|
|
|
|
text-align: initial;
|
|
|
|
}
|
2024-09-23 19:47:46 +02:00
|
|
|
.message_html {
|
|
|
|
padding: 8px;
|
|
|
|
text-align: initial;
|
|
|
|
white-space: normal;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
.message_pre {
|
|
|
|
padding: 8px;
|
|
|
|
text-align: initial;
|
|
|
|
white-space: pre-wrap;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
</style>
|