Changes
This commit is contained in:
107
src/components/admin/pages/Edit.svelte
Normal file
107
src/components/admin/pages/Edit.svelte
Normal file
@@ -0,0 +1,107 @@
|
||||
<script lang="ts">
|
||||
import {ArrowLeftSolid} from "flowbite-svelte-icons";
|
||||
import {Button, Card, Input, Label, Navbar, NavBrand, NavHamburger, NavUl, Spinner} from "flowbite-svelte";
|
||||
import {pageRepo} from "../repo/repo.js";
|
||||
import {mapToMap, nameRegex} from "../util.ts";
|
||||
import Editor from "./edit/Editor.svelte";
|
||||
import TypeAheadSearch from "../components/TypeAheadSearch.svelte";
|
||||
import {branches} from "../stores/stores.ts";
|
||||
|
||||
let pagesFuture = $pageRepo.listPages();
|
||||
let selected: number | null = null;
|
||||
|
||||
let selectedBranch: string = "master";
|
||||
let searchValue: string = "";
|
||||
|
||||
$: availableBranches = $branches.map((branch) => ({
|
||||
name: branch,
|
||||
value: branch
|
||||
}))
|
||||
|
||||
$: console.log(availableBranches)
|
||||
|
||||
async function createBranch() {
|
||||
const name = prompt("Branch name:")
|
||||
if (name) {
|
||||
await $pageRepo.createBranch(name)
|
||||
let inter = setInterval(() => {
|
||||
branches.reload()
|
||||
if ($branches.includes(name)) {
|
||||
selectedBranch = name
|
||||
searchValue = ""
|
||||
clearInterval(inter)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteBranch() {
|
||||
if (selectedBranch !== "master") {
|
||||
let conf = confirm("Are you sure you want to delete this branch?")
|
||||
if(conf) {
|
||||
await $pageRepo.deleteBranch(selectedBranch)
|
||||
let inter = setInterval(() => {
|
||||
branches.reload()
|
||||
if (!$branches.includes(selectedBranch)) {
|
||||
selectedBranch = "master"
|
||||
searchValue = ""
|
||||
clearInterval(inter)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
alert("You can't delete the master branch")
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<div class="flex flex-col h-screen overflow-scroll">
|
||||
<Navbar let:hidden let:toggle>
|
||||
<NavBrand href="#">
|
||||
<ArrowLeftSolid></ArrowLeftSolid>
|
||||
<span class="ml-4 self-center whitespace-nowrap text-xl font-semibold dark:text-white">
|
||||
Edit Pages
|
||||
</span>
|
||||
</NavBrand>
|
||||
</Navbar>
|
||||
<div class="p-4 flex-1">
|
||||
<div class="grid md:grid-cols-3 grid-cols-1 h-full gap-8">
|
||||
<Card class="h-full flex flex-col !max-w-full">
|
||||
{#await pagesFuture}
|
||||
<Spinner />
|
||||
{:then pages}
|
||||
<div class="border-b border-b-gray-600 pb-2 flex justify-between">
|
||||
<TypeAheadSearch items={availableBranches} bind:selected={selectedBranch} bind:searchValue />
|
||||
<div>
|
||||
<Button on:click={deleteBranch} color="ghost">Delete Branch</Button>
|
||||
<Button on:click={createBranch}>Create Branch</Button>
|
||||
</div>
|
||||
</div>
|
||||
{@const pagesMap = mapToMap(pages)}
|
||||
{#each pagesMap as [key, value]}
|
||||
<details>
|
||||
<summary class="p-4 transition-colors hover:bg-gray-700 cursor-pointer">{key}</summary>
|
||||
<ul>
|
||||
{#each value as page}
|
||||
{@const match = nameRegex.exec(page.path) ? nameRegex.exec(page.path)[0] : ""}
|
||||
{@const startIndex = page.path.indexOf(match)}
|
||||
{@const endIndex = startIndex + match.length}
|
||||
<li class="p-4 transition-colors hover:bg-gray-700 cursor-pointer" on:click|preventDefault={() => selected = page.id}>
|
||||
<span class:text-orange-600={selected === page.id}>{page.path.substring(0, startIndex)}</span><span class="text-white" class:!text-orange-500={selected === page.id}>{match}</span><span class:text-orange-600={selected === page.id}>{page.path.substring(endIndex, page.path.length)}</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</details>
|
||||
{/each}
|
||||
{:catch error}
|
||||
<p>{error.message}</p>
|
||||
{/await}
|
||||
</Card>
|
||||
<Card class="!max-w-full" style="grid-column: 2/4">
|
||||
{#if selected}
|
||||
<Editor pageId={selected} branch={selectedBranch} />
|
||||
{/if}
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,11 +21,12 @@
|
||||
<Navbar let:hidden let:toggle class="shadow-lg border-b">
|
||||
<NavBrand href="#">
|
||||
<span class="self-center whitespace-nowrap text-xl font-semibold dark:text-white">
|
||||
Eventplanner
|
||||
Admin-Tool
|
||||
</span>
|
||||
</NavBrand>
|
||||
<NavHamburger on:click={toggle} />
|
||||
<NavUl {hidden}>
|
||||
<NavLi href="#/edit">Edit Pages</NavLi>
|
||||
<NavLi href="#/perms">Permissions</NavLi>
|
||||
<NavLi on:click={() => showLogoutModal = true} class="cursor-pointer select-none">Logout</NavLi>
|
||||
</NavUl>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import {fly} from "svelte/transition";
|
||||
import {replace} from "svelte-spa-router";
|
||||
import {EyeOutline, EyeSlashOutline, EyeSolid} from "flowbite-svelte-icons";
|
||||
import {tokenStore} from "../repo/repo.js";
|
||||
import {fetchWithToken, tokenStore} from "../repo/repo.js";
|
||||
|
||||
let show = false;
|
||||
let loading = false;
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
async function handleSubmit() {
|
||||
loading = true;
|
||||
let res = await fetch("https://steamwar.de/eventplanner-api/data", {headers: {"X-SW-Auth": value}})
|
||||
let res = await fetchWithToken(value, "/data")
|
||||
loading = false;
|
||||
if(res.ok) {
|
||||
$tokenStore = value;
|
||||
|
||||
50
src/components/admin/pages/edit/Editor.svelte
Normal file
50
src/components/admin/pages/edit/Editor.svelte
Normal file
@@ -0,0 +1,50 @@
|
||||
<script lang="ts">
|
||||
import {Spinner, Toolbar, ToolbarButton, ToolbarGroup, Tooltip} from "flowbite-svelte";
|
||||
import {markdown} from "@codemirror/lang-markdown";
|
||||
import CodeMirror from "svelte-codemirror-editor";
|
||||
import {pageRepo} from "../../repo/repo.ts";
|
||||
import {base64ToBytes} from "../../util.ts";
|
||||
import type {Page} from "../../types/page.ts";
|
||||
import {materialDark} from '@ddietr/codemirror-themes/material-dark.js'
|
||||
import {EditOutline} from "flowbite-svelte-icons";
|
||||
|
||||
export let pageId: number;
|
||||
export let branch: string;
|
||||
$: pageFuture = $pageRepo.getPage(pageId).then(getPage);
|
||||
let pageContent = "";
|
||||
let page: Page | null = null;
|
||||
|
||||
function getPage(value: Page): Page {
|
||||
page = value;
|
||||
pageContent = new TextDecoder().decode(base64ToBytes(value.content));
|
||||
return value;
|
||||
}
|
||||
|
||||
function savePage() {
|
||||
let message = window.prompt("Commit message:")
|
||||
if (message) {
|
||||
$pageRepo.updatePage(pageId, pageContent, page!.sha, message)
|
||||
} else {
|
||||
alert("Commit message is required")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await pageFuture}
|
||||
<Spinner />
|
||||
{:then p}
|
||||
<div>
|
||||
<div>
|
||||
<Toolbar class="!bg-gray-900">
|
||||
<ToolbarGroup slot="end">
|
||||
<ToolbarButton color="primary" on:click={savePage}>
|
||||
Save
|
||||
</ToolbarButton>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
</div>
|
||||
<CodeMirror bind:value={pageContent} lang={markdown()} theme={materialDark} />
|
||||
</div>
|
||||
{:catch error}
|
||||
<p>{error.message}</p>
|
||||
{/await}
|
||||
Reference in New Issue
Block a user