Merge branch 'development' into f052_admin_area
This commit is contained in:
@@ -42,18 +42,6 @@
|
|||||||
<p class="mt-1 text-gray-600">Fügen Sie einem Tatort Bilder hinzu.</p>
|
<p class="mt-1 text-gray-600">Fügen Sie einem Tatort Bilder hinzu.</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="group relative rounded-lg p-6 text-sm leading-6 hover:bg-gray-50 w-1/4">
|
|
||||||
<div
|
|
||||||
class="flex h-11 w-11 items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white"
|
|
||||||
>
|
|
||||||
<FileRect class=" group-hover:text-indigo-600" {outline} />
|
|
||||||
</div>
|
|
||||||
<a href="/view" class="mt-6 block font-semibold text-gray-900">
|
|
||||||
Ansicht
|
|
||||||
<span class="absolute inset-0"></span>
|
|
||||||
</a>
|
|
||||||
<p class="mt-1 text-gray-600">Schau Dir einen Tatort in der 3D Ansicht an.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { getVorgaenge } from '$lib/server/vorgangService';
|
|||||||
import type { PageServerLoad } from '../../(token-based)/view/$types';
|
import type { PageServerLoad } from '../../(token-based)/view/$types';
|
||||||
|
|
||||||
export const load: PageServerLoad = async () => {
|
export const load: PageServerLoad = async () => {
|
||||||
const vorgangList = await getVorgaenge();
|
const vorgangList = getVorgaenge();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
vorgangList
|
vorgangList
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
import { client } from '$lib/minio';
|
|
||||||
import { fail } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
import vorgangNumberOccupied from '$lib/helper/vorgangNumberOccupied.js';
|
|
||||||
|
|
||||||
/** @type {import('./$types').Actions} */
|
|
||||||
export const actions = {
|
|
||||||
default: async ({ request }: {request: Request}) => {
|
|
||||||
const data = await request.formData();
|
|
||||||
const vorgangNumber = data.get('vorgangNumber');
|
|
||||||
const description = data.get('description');
|
|
||||||
|
|
||||||
if (!vorgangNumber) {
|
|
||||||
return fail(400, {
|
|
||||||
vorgangNumber,
|
|
||||||
description,
|
|
||||||
error: { vorgangNumber: 'Es muss eine Vorgangsnummer vorhanden sein.' }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await vorgangNumberOccupied(`${vorgangNumber}`)) {
|
|
||||||
return fail(400, {
|
|
||||||
vorgangNumber,
|
|
||||||
description,
|
|
||||||
error: { vorgangNumber: 'Die Vorgangsnummer wurde im System bereits angelegt.' }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = `${JSON.stringify({ vorgangNumber, description, version: 1 })}\n`;
|
|
||||||
|
|
||||||
await client.putObject('tatort', `${vorgangNumber}/config.json`, config, undefined, {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
});
|
|
||||||
|
|
||||||
return { success: true };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import Alert from '$lib/components/Alert.svelte';
|
|
||||||
import Button from '$lib/components/Button.svelte';
|
|
||||||
import Modal from '$lib/components/Modal/Modal.svelte';
|
|
||||||
import ModalTitle from '$lib/components/Modal/ModalTitle.svelte';
|
|
||||||
import ModalContent from '$lib/components/Modal/ModalContent.svelte';
|
|
||||||
import ModalFooter from '$lib/components/Modal/ModalFooter.svelte';
|
|
||||||
import Exclamation from '$lib/icons/Exclamation.svelte';
|
|
||||||
|
|
||||||
export let form;
|
|
||||||
|
|
||||||
let open = false;
|
|
||||||
$: open = form?.success ?? false;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="mx-auto max-w-2xl">
|
|
||||||
<div class="flex flex-col items-center justify-center w-full">
|
|
||||||
<h1 class="text-xl">Neuer Vorgang</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form method="POST">
|
|
||||||
<div class="space-y-12">
|
|
||||||
<div class="border-b border-gray-900/10 pb-12">
|
|
||||||
<p class="mt-8 text-sm leading-6 text-gray-600">
|
|
||||||
This information will be displayed publicly so be careful what you share.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8">
|
|
||||||
<div>
|
|
||||||
<label for="vorgangNumber" class="block text-sm font-medium leading-6 text-gray-900"
|
|
||||||
><span class="flex"
|
|
||||||
>{#if form?.error?.vorgangNumber}
|
|
||||||
<span class="inline-block mr-1"><Exclamation /></span>
|
|
||||||
{/if} Vorgangs-Nr.</span
|
|
||||||
></label
|
|
||||||
>
|
|
||||||
<div class="mt-2">
|
|
||||||
<div
|
|
||||||
class="flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-600"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
value={form?.vorgangNumber ?? ''}
|
|
||||||
type="text"
|
|
||||||
name="vorgangNumber"
|
|
||||||
id="vorgangNumber"
|
|
||||||
class="block flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 text-sm leading-6"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{#if form?.error?.vorgangNumber}
|
|
||||||
<p class="block text-sm leading-6 text-red-900 mt-2">{form.error.vorgangNumber}</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="description" class="block text-sm font-medium leading-6 text-gray-900"
|
|
||||||
><span class="flex"
|
|
||||||
>{#if form?.description}
|
|
||||||
<span class="inline-block mr-1"><Exclamation /></span>
|
|
||||||
{/if} Beschreibung</span
|
|
||||||
></label
|
|
||||||
>
|
|
||||||
<div class="mt-2">
|
|
||||||
<textarea
|
|
||||||
value={form?.description?.toString() ?? ''}
|
|
||||||
id="description"
|
|
||||||
name="description"
|
|
||||||
rows="3"
|
|
||||||
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
|
||||||
></textarea>
|
|
||||||
</div>
|
|
||||||
{#if form?.error}
|
|
||||||
<p class="block text-sm leading-6 text-red-900 mt-2">{form.description}</p>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label for="vorgang-token">
|
|
||||||
<span >Zugangstoken (optional) </span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="mt-2">
|
|
||||||
<div
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="vorgang-token"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6 flex items-center justify-end gap-x-6">
|
|
||||||
<button type="button" class="text-sm font-semibold leading-6 text-gray-900">Cancel</button>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
|
|
||||||
>Save</Button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<Modal {open}
|
|
||||||
><ModalTitle>vorgang anlegen</ModalTitle><ModalContent>
|
|
||||||
{#if form?.success}
|
|
||||||
<Alert class="w-full">Vorgang erfolgreich angelegt</Alert>
|
|
||||||
{:else}
|
|
||||||
<Alert class="w-full" type="error">Fehler beim Upload</Alert>
|
|
||||||
{/if}
|
|
||||||
</ModalContent>
|
|
||||||
<ModalFooter><Button on:click={() => (open = false)}>Ok</Button></ModalFooter>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
@@ -17,11 +17,11 @@ const isRequiredFieldValid = (value: unknown) => {
|
|||||||
export const actions = {
|
export const actions = {
|
||||||
url: async ({ request }: { request: Request }) => {
|
url: async ({ request }: { request: Request }) => {
|
||||||
const data = await request.formData();
|
const data = await request.formData();
|
||||||
const vorgangName = data.get('vorgang');
|
const vorgangName: string | null = data.get('vorgang') as string;
|
||||||
const crimeName = data.get('name');
|
const crimeName: string | null = data.get('name') as string;
|
||||||
const type = data.get('type');
|
const type: string | null = data.get('type') as string;
|
||||||
const vorgangPIN = data.get('vorgangPIN');
|
const vorgangPIN: string | null = data.get('vorgangPIN') as string;
|
||||||
const fileName = data.get('fileName');
|
const fileName: string | null = data.get('fileName') as string;
|
||||||
|
|
||||||
const vorgangExists = vorgangNameExists(vorgangName);
|
const vorgangExists = vorgangNameExists(vorgangName);
|
||||||
let vorgangToken;
|
let vorgangToken;
|
||||||
|
|||||||
@@ -59,8 +59,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handle_input(ev: KeyboardEvent, i: number) {
|
async function handleEditFieldInput(ev: KeyboardEvent, listItemIndex: number) {
|
||||||
let item = crimesList[i];
|
let item = crimesList[listItemIndex];
|
||||||
if (ev.key == 'Escape') {
|
if (ev.key == 'Escape') {
|
||||||
let text_field_id = `label__${item.name}`;
|
let text_field_id = `label__${item.name}`;
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
// construct PUT URL
|
// construct PUT URL
|
||||||
const url = $page.url;
|
const url = $page.url.pathname.split('?')[0];
|
||||||
|
|
||||||
let data_obj: { new_name: string; old_name: string } = { new_name: '', old_name: '' };
|
let data_obj: { new_name: string; old_name: string } = { new_name: '', old_name: '' };
|
||||||
data_obj['new_name'] = new_name;
|
data_obj['new_name'] = new_name;
|
||||||
@@ -129,13 +129,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setClipboard(text) {
|
function constructMailToLink() {
|
||||||
const type = "text/plain";
|
const subject = "Link zum Tatvorgang";
|
||||||
const clipboardItemData = {
|
const link = $page.url.toString().split('?')[0];
|
||||||
[type]: text,
|
const body = `Hallo,
|
||||||
};
|
|
||||||
const clipboardItem = new ClipboardItem(clipboardItemData);
|
hier ist der Link zum Tatvorgang:
|
||||||
await navigator.clipboard.write([clipboardItem]);
|
${link}
|
||||||
|
|
||||||
|
Der Zugangs-PIN wird zur Sicherheit über einen zweiten Kommunikationskanal übermittelt.
|
||||||
|
|
||||||
|
Mit freundlichen Grüßen,
|
||||||
|
`;
|
||||||
|
|
||||||
|
const mailtoLink = `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
||||||
|
|
||||||
|
return mailtoLink;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -144,12 +153,12 @@
|
|||||||
<h1 class="text-xl">Vorgang {vorgang.name}</h1>
|
<h1 class="text-xl">Vorgang {vorgang.name}</h1>
|
||||||
{#if data?.user?.admin}
|
{#if data?.user?.admin}
|
||||||
Zugangs-PIN: {vorgang.pin}
|
Zugangs-PIN: {vorgang.pin}
|
||||||
<Button on:click={() => setClipboard($page.url.toString().split('?')[0])}>Copy Link</Button>
|
<a href="{constructMailToLink()}"><Button>Share Link</Button></a>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="mx-auto flex justify-center max-w-7xl h-full">
|
<div class="mx-auto flex justify-center max-w-7xl h-full">
|
||||||
<ul class="divide-y divide-gray-100">
|
<ul class="divide-y divide-gray-100">
|
||||||
{#each crimesList as item, i}
|
{#each crimesList as item, crimeListItemIndex}
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
href="/view/{$page.params.vorgang}/{item.name}?pin={vorgangPIN}"
|
href="/view/{$page.params.vorgang}/{item.name}?pin={vorgangPIN}"
|
||||||
@@ -168,12 +177,12 @@
|
|||||||
tabindex="0"
|
tabindex="0"
|
||||||
aria-label="Dateiname bearbeiten"
|
aria-label="Dateiname bearbeiten"
|
||||||
on:focusout={() => {
|
on:focusout={() => {
|
||||||
defocus_element(i);
|
defocus_element(crimeListItemIndex);
|
||||||
}}
|
}}
|
||||||
on:keydown|stopPropagation={// event needed to identify ID
|
on:keydown|stopPropagation={// event needed to identify ID
|
||||||
// TO-DO: check if event is needed or if index is sufficient
|
// TO-DO: check if event is needed or if index is sufficient
|
||||||
async (ev) => {
|
async (ev) => {
|
||||||
handle_input(ev, i);
|
handleEditFieldInput(ev, crimeListItemIndex);
|
||||||
}}>{item.name}</span
|
}}>{item.name}</span
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,20 @@ import { client } from '$lib/minio';
|
|||||||
import { json } from '@sveltejs/kit';
|
import { json } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
|
||||||
// rename operation
|
// rename operation for crimes
|
||||||
export async function PUT({ request }: {request: Request}) {
|
export async function PUT({ request }: {request: Request}) {
|
||||||
const data = await request.json();
|
const data = await request.json();
|
||||||
|
|
||||||
|
|
||||||
// Vorgang
|
// Vorgang
|
||||||
const vorgang = request.url.split('/').at(-1);
|
const vorgangToken = request.url.split('/').at(-1);
|
||||||
|
|
||||||
// prepare copy, incl. check if new name exists already
|
// prepare copy, incl. check if new name exists already
|
||||||
const old_name = data["old_name"];
|
const crimeOldName = data["old_name"];
|
||||||
const src_full_path = `/tatort/${vorgang}/${old_name}`;
|
const crimeS3FullBucketPathOld = `/tatort/${vorgangToken}/${crimeOldName}`;
|
||||||
const new_name = `${vorgang}/${data["new_name"]}`;
|
const crimeNewName = `${vorgangToken}/${data["new_name"]}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await client.statObject('tatort', new_name);
|
await client.statObject('tatort', crimeNewName);
|
||||||
return json({ msg: 'Die Datei existiert bereits.' }, { status: 400 });
|
return json({ msg: 'Die Datei existiert bereits.' }, { status: 400 });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// continue operation
|
// continue operation
|
||||||
@@ -24,10 +23,10 @@ export async function PUT({ request }: {request: Request}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// actual copy operation
|
// actual copy operation
|
||||||
await client.copyObject('tatort', new_name, src_full_path)
|
await client.copyObject('tatort', crimeNewName, crimeS3FullBucketPathOld)
|
||||||
|
|
||||||
// delete
|
// delete
|
||||||
await client.removeObject('tatort', `${vorgang}/${old_name}`)
|
await client.removeObject('tatort', `${vorgangToken}/${crimeOldName}`)
|
||||||
|
|
||||||
// return success or failure
|
// return success or failure
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import { redirect } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export const actions = {
|
|
||||||
default: async ({request}: {request: Request}) => {
|
|
||||||
const data = await request.formData();
|
|
||||||
const vorgangId = data.get('vorgang-id');
|
|
||||||
const vorgangToken = data.get('vorgang-token');
|
|
||||||
|
|
||||||
if( vorgangId && vorgangToken) throw redirect(303, `/list/${vorgangId}?token=${vorgangToken}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import BaseInputField from '$lib/components/BaseInputField.svelte';
|
|
||||||
import Button from '$lib/components/Button.svelte';
|
|
||||||
import ArrowRight from '$lib/icons/Arrow-right.svelte';
|
|
||||||
|
|
||||||
export let form;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="mx-auto max-w-2xl">
|
|
||||||
<div class="flex flex-col items-center justify-center w-full">
|
|
||||||
<h1 class="text-xl">Vorgang ansehen</h1>
|
|
||||||
</div>
|
|
||||||
<p class="mt-8 mb-8 text-sm leading-6 text-gray-600">
|
|
||||||
Anhand der Vorgangsnummer werden Sie zu den Dateien des Vorgangs weitergeleitet und können sich
|
|
||||||
den Vorgang dann ansehen.
|
|
||||||
</p>
|
|
||||||
<form method="POST">
|
|
||||||
<BaseInputField
|
|
||||||
id="vorgang-id"
|
|
||||||
name="vorgang-id"
|
|
||||||
label="Vorgangskennung"
|
|
||||||
type="text"
|
|
||||||
value={form?.vorgangId}
|
|
||||||
/>
|
|
||||||
<div class="mt-5">
|
|
||||||
<BaseInputField
|
|
||||||
id="vorgang-token"
|
|
||||||
name="vorgang-token"
|
|
||||||
label="Zugangstoken"
|
|
||||||
type="text"
|
|
||||||
value={form?.vorgangToken}
|
|
||||||
error={form?.error?.message}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-end pt-4">
|
|
||||||
<Button type="submit"><ArrowRight /></Button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
Reference in New Issue
Block a user