Merge pull request #13 from archtika/devel

Add pagination for logs and update deploy action
This commit is contained in:
Thilo Hohlt
2024-09-15 22:42:59 +02:00
committed by GitHub
6 changed files with 118 additions and 23 deletions

View File

@@ -31,8 +31,9 @@ jobs:
- name: Deploy to demo server - name: Deploy to demo server
run: | run: |
nix run nixpkgs#nixos-rebuild -- switch \ nix run nixpkgs#nixos-rebuild -- switch \
--flake .#${{ github.event.workflow_run.head_branch == 'devel' && 'qs' || 'prod' }} \ --flake github:archtika/archtika/${{ github.event.workflow_run.head_branch }}#${{ github.event.workflow_run.head_branch == 'devel' && 'qs' || 'prod' }} \
--fast \ --fast \
--refresh \
--build-host ${{ env.SERVER_USER }}@${{ github.event.workflow_run.head_branch == 'devel' && env.QS_SERVER_IP || env.PROD_SERVER_IP }} \ --build-host ${{ env.SERVER_USER }}@${{ github.event.workflow_run.head_branch == 'devel' && env.QS_SERVER_IP || env.PROD_SERVER_IP }} \
--target-host ${{ env.SERVER_USER }}@${{ github.event.workflow_run.head_branch == 'devel' && env.QS_SERVER_IP || env.PROD_SERVER_IP }} \ --target-host ${{ env.SERVER_USER }}@${{ github.event.workflow_run.head_branch == 'devel' && env.QS_SERVER_IP || env.PROD_SERVER_IP }} \
--use-remote-sudo --use-remote-sudo

View File

@@ -68,9 +68,9 @@
]; ];
locations = { locations = {
"/" = { "/" = {
root = "/var/www/archtika-websites/"; root = "/var/www/archtika-websites";
index = "index.html"; index = "index.html";
tryFiles = "$uri $uri/ $uri.html $uri/index.html index.html =404"; tryFiles = "$uri $uri/ $uri.html =404";
extraConfig = '' extraConfig = ''
autoindex on; autoindex on;
''; '';

View File

@@ -160,14 +160,12 @@ in
"/previews/" = { "/previews/" = {
alias = "/var/www/archtika-websites/previews/"; alias = "/var/www/archtika-websites/previews/";
index = "index.html"; index = "index.html";
tryFiles = "$uri $uri/ $uri.html $uri/index.html index.html =404"; tryFiles = "$uri $uri/ $uri.html =404";
}; };
"/api/" = { "/api/" = {
proxyPass = "http://localhost:${toString cfg.apiPort}/"; proxyPass = "http://localhost:${toString cfg.apiPort}/";
extraConfig = '' extraConfig = ''
default_type application/json; default_type application/json;
proxy_hide_header Content-Location;
add_header Content-Location /api/$upstream_http_content_location;
proxy_set_header Connection ""; proxy_set_header Connection "";
proxy_http_version 1.1; proxy_http_version 1.1;
''; '';
@@ -179,9 +177,9 @@ in
forceSSL = true; forceSSL = true;
locations = { locations = {
"/" = { "/" = {
alias = "/var/www/archtika-websites/$subdomain/"; root = "/var/www/archtika-websites/$subdomain";
index = "index.html"; index = "index.html";
tryFiles = "$uri $uri/ $uri.html $uri/index.html index.html =404"; tryFiles = "$uri $uri/ $uri.html =404";
}; };
}; };
}; };

View File

@@ -6,6 +6,8 @@ export const load: PageServerLoad = async ({ parent, fetch, params, cookies, url
const userFilter = url.searchParams.get("logs_filter_user"); const userFilter = url.searchParams.get("logs_filter_user");
const resourceFilter = url.searchParams.get("logs_filter_resource"); const resourceFilter = url.searchParams.get("logs_filter_resource");
const operationFilter = url.searchParams.get("logs_filter_operation"); const operationFilter = url.searchParams.get("logs_filter_operation");
const currentPage = Number.parseInt(url.searchParams.get("logs_results_page") ?? "1");
const resultOffset = currentPage === 1 ? 0 : currentPage * 50;
const searchParams = new URLSearchParams(); const searchParams = new URLSearchParams();
@@ -23,7 +25,7 @@ export const load: PageServerLoad = async ({ parent, fetch, params, cookies, url
searchParams.append("operation", `eq.${operationFilter.toUpperCase()}`); searchParams.append("operation", `eq.${operationFilter.toUpperCase()}`);
} }
const constructedFetchUrl = `${baseFetchUrl}&${searchParams.toString()}`; const constructedFetchUrl = `${baseFetchUrl}&${searchParams.toString()}&limit=50&offset=${resultOffset}`;
const changeLogData = await fetch(constructedFetchUrl, { const changeLogData = await fetch(constructedFetchUrl, {
method: "GET", method: "GET",

View File

@@ -42,6 +42,8 @@
const { user, change_log, media, ...restTables } = tables; const { user, change_log, media, ...restTables } = tables;
resources = restTables; resources = restTables;
} }
let logsSection: HTMLElement;
</script> </script>
<WebsiteEditor <WebsiteEditor
@@ -50,14 +52,14 @@
title={data.website.title} title={data.website.title}
previewContent={data.home.main_content} previewContent={data.home.main_content}
> >
<section id="logs"> <section id="logs" bind:this={logsSection}>
<hgroup> <hgroup>
<h2> <h2>
<a href="#logs">Logs</a> <a href="#logs">Logs</a>
</h2> </h2>
<p> <p>
<strong>{data.resultChangeLogCount}</strong> <strong>{data.resultChangeLogCount.toLocaleString("en", { useGrouping: true })}</strong>
<small>results</small> <small>result(s)</small>
</p> </p>
</hgroup> </hgroup>
<details> <details>
@@ -111,6 +113,7 @@
> >
</select> </select>
</label> </label>
<input type="hidden" name="logs_results_page" value={1} />
<button type="submit">Submit</button> <button type="submit">Submit</button>
</form> </form>
</details> </details>
@@ -155,6 +158,106 @@
{/each} {/each}
</tbody> </tbody>
</table> </table>
{#snippet commonFilterInputs()}
<input
type="hidden"
name="logs_filter_user"
value={$page.url.searchParams.get("logs_filter_user")}
/>
<input
type="hidden"
name="logs_filter_resource"
value={$page.url.searchParams.get("logs_filter_resource")}
/>
<input
type="hidden"
name="logs_filter_operation"
value={$page.url.searchParams.get("logs_filter_operation")}
/>
{/snippet}
<div class="pagination">
<p>
{$page.url.searchParams.get("logs_results_page") ?? 1} / {Math.max(
Math.floor(data.resultChangeLogCount / 50),
1
)}
</p>
<form method="GET" onsubmit={() => logsSection.scrollIntoView()}>
<input type="hidden" name="logs_results_page" value={1} />
{@render commonFilterInputs()}
<button
type="submit"
disabled={($page.url.searchParams.get("logs_results_page") ?? "1") === "1"}
>First</button
>
</form>
<form method="GET" onsubmit={() => logsSection.scrollIntoView()}>
<input
type="hidden"
name="logs_results_page"
value={Math.max(
1,
Number.parseInt($page.url.searchParams.get("logs_results_page") ?? "1") - 1
)}
/>
{@render commonFilterInputs()}
<button
type="submit"
disabled={($page.url.searchParams.get("logs_results_page") ?? "1") === "1"}
>Previous</button
>
</form>
<form method="GET" onsubmit={() => logsSection.scrollIntoView()}>
<input
type="hidden"
name="logs_results_page"
value={Math.min(
Math.max(Math.floor(data.resultChangeLogCount / 50), 1),
Number.parseInt($page.url.searchParams.get("logs_results_page") ?? "1") + 1
)}
/>
{@render commonFilterInputs()}
<button
type="submit"
disabled={($page.url.searchParams.get("logs_results_page") ?? "1") ===
Math.max(Math.floor(data.resultChangeLogCount / 50), 1).toString()}>Next</button
>
</form>
<form method="GET" onsubmit={() => logsSection.scrollIntoView()}>
<input
type="hidden"
name="logs_results_page"
value={Math.max(Math.floor(data.resultChangeLogCount / 50), 1)}
/>
{@render commonFilterInputs()}
<button
type="submit"
disabled={($page.url.searchParams.get("logs_results_page") ?? "1") ===
Math.max(Math.floor(data.resultChangeLogCount / 50), 1).toString()}>Last</button
>
</form>
</div>
</div> </div>
</section> </section>
</WebsiteEditor> </WebsiteEditor>
<style>
.pagination {
display: flex;
align-items: center;
margin-inline: var(--space-2xs);
margin-block: var(--space-s);
flex-wrap: wrap;
gap: var(--space-xs);
justify-content: end;
}
.pagination > form:first-of-type {
margin-inline-start: auto;
}
button[disabled] {
opacity: 0.5;
pointer-events: none;
}
</style>

View File

@@ -3,20 +3,11 @@
import { page } from "$app/stores"; import { page } from "$app/stores";
import type { LayoutServerData } from "./$types"; import type { LayoutServerData } from "./$types";
import type { Snippet } from "svelte"; import type { Snippet } from "svelte";
import { beforeNavigate, afterNavigate } from "$app/navigation"; import { navigating } from "$app/stores";
import LoadingSpinner from "$lib/components/LoadingSpinner.svelte"; import LoadingSpinner from "$lib/components/LoadingSpinner.svelte";
const { data, children }: { data: LayoutServerData; children: Snippet } = $props(); const { data, children }: { data: LayoutServerData; children: Snippet } = $props();
let loading = $state(false);
beforeNavigate(() => {
loading = true;
});
afterNavigate(() => {
loading = false;
});
const isProjectRoute = $derived($page.url.pathname.startsWith("/website") && !$page.error); const isProjectRoute = $derived($page.url.pathname.startsWith("/website") && !$page.error);
const routeName = $derived( const routeName = $derived(
$page.url.pathname === "/" $page.url.pathname === "/"
@@ -25,7 +16,7 @@
); );
</script> </script>
{#if loading} {#if $navigating && ["link", "goto"].includes($navigating.type)}
<LoadingSpinner /> <LoadingSpinner />
{/if} {/if}