-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add admin view for unparseable webhooks
- Loading branch information
Showing
8 changed files
with
253 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
.col-auto { | ||
flex: 0 0 auto; | ||
width: auto; | ||
flex-direction: column; | ||
} | ||
|
||
.row-centered { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,46 @@ | ||
import { axiosAPI } from './../axios'; | ||
import type { Table, UserForAdmin } from './../types'; | ||
import type { Page, Table, UnparseableWebhook, UserForAdmin } from './../types'; | ||
import { loadUser } from './../stores'; | ||
|
||
export const getTables = async (): Promise<Table[]> => { | ||
return await axiosAPI.get<Table[]>('/fapi/admin/table').then((res) => res.data); | ||
return await axiosAPI.get<Table[]>('/fapi/admin/table').then((res) => res.data); | ||
}; | ||
|
||
export const getUsers = async (): Promise<UserForAdmin[]> => { | ||
return await axiosAPI.get<UserForAdmin[]>('/fapi/admin/user').then((res) => res.data); | ||
return await axiosAPI.get<UserForAdmin[]>('/fapi/admin/user').then((res) => res.data); | ||
}; | ||
|
||
export const deleteUsers = async (ids: string[]) => { | ||
await axiosAPI({ | ||
method: 'delete', | ||
url: '/fapi/admin/user', | ||
data: JSON.stringify(ids), | ||
headers: { | ||
'Content-Type': 'application/json' | ||
} | ||
}); | ||
await axiosAPI({ | ||
method: 'delete', | ||
url: '/fapi/admin/user', | ||
data: JSON.stringify(ids), | ||
headers: { | ||
'Content-Type': 'application/json' | ||
} | ||
}); | ||
}; | ||
|
||
export const setUsersTeacher = async (ids: string[]) => { | ||
await axiosAPI({ | ||
method: 'patch', | ||
url: '/fapi/admin/teacher', | ||
data: JSON.stringify(ids), | ||
headers: { | ||
'Content-Type': 'application/json' | ||
} | ||
}); | ||
await loadUser(); | ||
await axiosAPI({ | ||
method: 'patch', | ||
url: '/fapi/admin/teacher', | ||
data: JSON.stringify(ids), | ||
headers: { | ||
'Content-Type': 'application/json' | ||
} | ||
}); | ||
await loadUser(); | ||
}; | ||
|
||
export const getUnparseableWebhooks = async (page: number, per_page: number): Promise<Page<UnparseableWebhook>> => { | ||
return await axiosAPI.get<Page<UnparseableWebhook>>(`/fapi/admin/unparseable_webhooks?page=${page}&per_page=${per_page}`) | ||
.then((res) => res.data); | ||
}; | ||
|
||
export const deleteUnparseableWebhooks = async () => { | ||
await axiosAPI({ | ||
method: 'delete', | ||
url: '/fapi/admin/unparseable_webhooks' | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,46 @@ | ||
import type { Table, UserForAdmin } from './../types'; | ||
import type { Page, Table, UnparseableWebhook, UserForAdmin } from './../types'; | ||
import * as mock from './../mock'; | ||
import { loadUser } from './../stores'; | ||
|
||
export const getTables = async (): Promise<Table[]> => { | ||
return [ | ||
{ | ||
name: 'table_1', | ||
row_count: 4 | ||
}, | ||
{ | ||
name: 'table_2', | ||
row_count: 13 | ||
} | ||
]; | ||
return [ | ||
{ | ||
name: 'table_1', | ||
row_count: 4 | ||
}, | ||
{ | ||
name: 'table_2', | ||
row_count: 13 | ||
} | ||
]; | ||
}; | ||
|
||
export const getUsers = async (): Promise<UserForAdmin[]> => { | ||
return mock.users; | ||
return mock.users; | ||
}; | ||
|
||
export const deleteUsers = async (ids: string[]) => { | ||
mock.deleteUsers(ids); | ||
mock.deleteUsers(ids); | ||
}; | ||
|
||
export const setUsersTeacher = async (ids: string[]) => { | ||
mock.users.filter((u) => ids.includes(u.id)).forEach((u) => (u.teacher = true)); | ||
await loadUser(); | ||
mock.users.filter((u) => ids.includes(u.id)).forEach((u) => (u.teacher = true)); | ||
await loadUser(); | ||
}; | ||
|
||
export const getUnparseableWebhooks = async (page: number, per_page: number): Promise<Page<UnparseableWebhook>> => { | ||
const start = page == 1 ? 0 : (page - 1) * per_page; | ||
const end = start + per_page; | ||
const items = mock.unparseable_webhooks.slice(start, end); | ||
return { | ||
page: page, | ||
per_page: per_page, | ||
total_count: mock.unparseable_webhooks.length, | ||
total_page: Math.ceil(mock.unparseable_webhooks.length / per_page), | ||
data: items, | ||
}; | ||
}; | ||
|
||
export const deleteUnparseableWebhooks = async () => { | ||
mock.unparseable_webhooks.splice(0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
<script lang="ts"> | ||
import Icon from '@iconify/svelte'; | ||
import type { Page, UnparseableWebhook } from '$lib/types'; | ||
import api from '$lib/api'; | ||
import '$css/table.css'; | ||
import '$css/grid.css'; | ||
let pageNumber = 1; | ||
let storedPage: Page<UnparseableWebhook>; | ||
async function getItemsAndStoreThem() { | ||
storedPage = await api.getUnparseableWebhooks(pageNumber, 15); | ||
console.dir(storedPage); | ||
return storedPage; | ||
} | ||
let itemPromise = getItemsAndStoreThem(); | ||
async function deleteAll() { | ||
await api.deleteUnparseableWebhooks(); | ||
itemPromise = getItemsAndStoreThem(); | ||
} | ||
async function copy(text: string) { | ||
await navigator.clipboard.writeText(text); | ||
} | ||
async function gotoPrevious() { | ||
pageNumber -= 1; | ||
await getItemsAndStoreThem(); | ||
} | ||
async function gotoNext() { | ||
pageNumber += 1; | ||
await getItemsAndStoreThem(); | ||
} | ||
</script> | ||
|
||
<div class="text-column"> | ||
<h3>Users</h3> | ||
|
||
{#await itemPromise} | ||
<p class="p-white">...loading items</p> | ||
<!-- eslint-disable @typescript-eslint/no-unused-vars --> | ||
{:then page} | ||
<div class="mb-3 row"> | ||
<span class="col-sm-1">Bulk actions:</span> | ||
<button type="button" on:click={deleteAll} class="col-sm-1 btn btn-danger" | ||
>Delete all | ||
</button | ||
> | ||
</div> | ||
|
||
<table class="table"> | ||
<thead> | ||
<tr> | ||
<th scope="col">Created at</th> | ||
<th scope="col">Origin</th> | ||
<th scope="col">Event</th> | ||
<th scope="col">Error</th> | ||
<th scope="col" class="clipped">Payload</th> | ||
<th scope="col"></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{#each storedPage.data as item} | ||
<tr> | ||
<td>{item.created_at.toISOString()}</td> | ||
<td>{item.origin}</td> | ||
<td>{item.event}</td> | ||
<td>{item.error}</td> | ||
<td class="clipped">{item.payload}</td> | ||
<td> | ||
<button type="button" class="btn-smooth" aria-label="Copy to clipboard" | ||
on:click={() => copy(item.payload)}> | ||
<Icon icon="mingcute:copy-2-line" inline /> | ||
</button> | ||
</td> | ||
</tr> | ||
{/each} | ||
</tbody> | ||
</table> | ||
{#if page.total_page > 1} | ||
<div class="row-centered"> | ||
<div class="col-auto"> | ||
{#if pageNumber > 1} | ||
<button type="button" class="btn-smooth btn-pagination" aria-label="Previous" on:click={gotoPrevious}> | ||
<Icon icon="grommet-icons:caret-previous" inline /> | ||
</button> | ||
{/if} | ||
</div> | ||
<div class="col-auto"> | ||
Page {pageNumber} | ||
</div> | ||
<div class="col-auto"> | ||
{#if pageNumber < page.total_page} | ||
<button type="button" class="btn-smooth btn-pagination" aria-label="Next" on:click={gotoNext}> | ||
<Icon icon="grommet-icons:caret-next" inline /> | ||
</button> | ||
{/if} | ||
</div> | ||
</div> | ||
{/if} | ||
{:catch error} | ||
<p style="color: red">{error.message}</p> | ||
{/await} | ||
</div> | ||
|
||
<style> | ||
.clipped { | ||
word-wrap: break-word; | ||
max-width: 150px; | ||
white-space: nowrap; | ||
text-overflow: ellipsis; | ||
overflow: hidden; | ||
} | ||
.btn-smooth { | ||
background: none; | ||
border: none; | ||
} | ||
.btn-smooth:hover { | ||
background: lightgray; | ||
border-radius: 6px; | ||
} | ||
.btn-pagination { | ||
color: cornflowerblue; | ||
font-size: 43px; | ||
} | ||
.col-auto { | ||
display: flex; | ||
justify-content: center; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const csr = true; | ||
|
||
// since there's no dynamic data here, we can prerender | ||
// it so that it gets served as a static asset in production | ||
export const prerender = true; |