|
|
@ -41,13 +41,19 @@ const ThumbnailManager: Component = () => {
|
|
|
|
cropStart: cropStart,
|
|
|
|
cropStart: cropStart,
|
|
|
|
cropEnd: cropEnd,
|
|
|
|
cropEnd: cropEnd,
|
|
|
|
locationStart: locationStart,
|
|
|
|
locationStart: locationStart,
|
|
|
|
locationEnd: locationEnd
|
|
|
|
locationEnd: locationEnd,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setTemplates(templateList);
|
|
|
|
setTemplates(templateList);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const submitHandler = async (origName: string, noImageIsError: boolean, errorList: Accessor<string[]>, setErrorList: Setter<string[]>, event: SubmitEvent): Promise<Template | null> => {
|
|
|
|
const submitHandler = async (
|
|
|
|
|
|
|
|
origName: string,
|
|
|
|
|
|
|
|
noImageIsError: boolean,
|
|
|
|
|
|
|
|
errorList: Accessor<string[]>,
|
|
|
|
|
|
|
|
setErrorList: Setter<string[]>,
|
|
|
|
|
|
|
|
event: SubmitEvent,
|
|
|
|
|
|
|
|
): Promise<Template | null> => {
|
|
|
|
setErrorList([]);
|
|
|
|
setErrorList([]);
|
|
|
|
|
|
|
|
|
|
|
|
const form = event.currentTarget as HTMLFormElement;
|
|
|
|
const form = event.currentTarget as HTMLFormElement;
|
|
|
@ -67,7 +73,16 @@ const ThumbnailManager: Component = () => {
|
|
|
|
const locEndX = parseInt(formData.get("locendx") as string, 10);
|
|
|
|
const locEndX = parseInt(formData.get("locendx") as string, 10);
|
|
|
|
const locEndY = parseInt(formData.get("locendy") as string, 10);
|
|
|
|
const locEndY = parseInt(formData.get("locendy") as string, 10);
|
|
|
|
|
|
|
|
|
|
|
|
if (isNaN(cropStartX) || isNaN(cropStartY) || isNaN(cropEndX) || isNaN(cropEndY) || isNaN(locStartX) || isNaN(locStartY) || isNaN(locEndX) || isNaN(locEndY)) {
|
|
|
|
if (
|
|
|
|
|
|
|
|
isNaN(cropStartX) ||
|
|
|
|
|
|
|
|
isNaN(cropStartY) ||
|
|
|
|
|
|
|
|
isNaN(cropEndX) ||
|
|
|
|
|
|
|
|
isNaN(cropEndY) ||
|
|
|
|
|
|
|
|
isNaN(locStartX) ||
|
|
|
|
|
|
|
|
isNaN(locStartY) ||
|
|
|
|
|
|
|
|
isNaN(locEndX) ||
|
|
|
|
|
|
|
|
isNaN(locEndY)
|
|
|
|
|
|
|
|
) {
|
|
|
|
setErrorList((errors) => {
|
|
|
|
setErrorList((errors) => {
|
|
|
|
errors.push("All crop and location information must be entered.");
|
|
|
|
errors.push("All crop and location information must be entered.");
|
|
|
|
return errors;
|
|
|
|
return errors;
|
|
|
@ -108,12 +123,15 @@ const ThumbnailManager: Component = () => {
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const submitURL = (origName === "") ? "/thrimshim/add-template" : `/thrimshim/update-template/${encodeURIComponent(origName)}`;
|
|
|
|
const submitURL =
|
|
|
|
|
|
|
|
origName === ""
|
|
|
|
|
|
|
|
? "/thrimshim/add-template"
|
|
|
|
|
|
|
|
: `/thrimshim/update-template/${encodeURIComponent(origName)}`;
|
|
|
|
const submitDataJSON = JSON.stringify(Object.fromEntries(submitData));
|
|
|
|
const submitDataJSON = JSON.stringify(Object.fromEntries(submitData));
|
|
|
|
const submitResponse = await fetch(submitURL, {
|
|
|
|
const submitResponse = await fetch(submitURL, {
|
|
|
|
method: "POST",
|
|
|
|
method: "POST",
|
|
|
|
body: submitDataJSON,
|
|
|
|
body: submitDataJSON,
|
|
|
|
headers: { "Content-Type": "application/json" }
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
});
|
|
|
|
});
|
|
|
|
if (!submitResponse.ok) {
|
|
|
|
if (!submitResponse.ok) {
|
|
|
|
const errorText = await submitResponse.text();
|
|
|
|
const errorText = await submitResponse.text();
|
|
|
@ -132,7 +150,7 @@ const ThumbnailManager: Component = () => {
|
|
|
|
cropStart: { x: cropStartX, y: cropStartY },
|
|
|
|
cropStart: { x: cropStartX, y: cropStartY },
|
|
|
|
cropEnd: { x: cropEndX, y: cropEndY },
|
|
|
|
cropEnd: { x: cropEndX, y: cropEndY },
|
|
|
|
locationStart: { x: locStartX, y: locStartY },
|
|
|
|
locationStart: { x: locStartX, y: locStartY },
|
|
|
|
locationEnd: { x: locEndX, y: locEndY }
|
|
|
|
locationEnd: { x: locEndX, y: locEndY },
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -158,7 +176,13 @@ const ThumbnailManager: Component = () => {
|
|
|
|
<form
|
|
|
|
<form
|
|
|
|
class={styles.templatesListRow}
|
|
|
|
class={styles.templatesListRow}
|
|
|
|
onSubmit={async (event) => {
|
|
|
|
onSubmit={async (event) => {
|
|
|
|
const submitData = await submitHandler(template().name, false, formErrors, setFormErrors, event);
|
|
|
|
const submitData = await submitHandler(
|
|
|
|
|
|
|
|
template().name,
|
|
|
|
|
|
|
|
false,
|
|
|
|
|
|
|
|
formErrors,
|
|
|
|
|
|
|
|
setFormErrors,
|
|
|
|
|
|
|
|
event,
|
|
|
|
|
|
|
|
);
|
|
|
|
if (submitData) {
|
|
|
|
if (submitData) {
|
|
|
|
setTemplates((templateList) => {
|
|
|
|
setTemplates((templateList) => {
|
|
|
|
templateList[index] = submitData;
|
|
|
|
templateList[index] = submitData;
|
|
|
@ -175,39 +199,30 @@ const ThumbnailManager: Component = () => {
|
|
|
|
<div>{template().description}</div>
|
|
|
|
<div>{template().description}</div>
|
|
|
|
<div>{template().attribution}</div>
|
|
|
|
<div>{template().attribution}</div>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
({template().cropStart.x}, {template().cropStart.y})
|
|
|
|
({template().cropStart.x}, {template().cropStart.y}) to (
|
|
|
|
to
|
|
|
|
{template().cropEnd.x}, {template().cropEnd.y})
|
|
|
|
({template().cropEnd.x}, {template().cropEnd.y})
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
({template().locationStart.x}, {template().locationStart.y})
|
|
|
|
({template().locationStart.x}, {template().locationStart.y}) to (
|
|
|
|
to
|
|
|
|
{template().locationEnd.x}, {template().locationEnd.y})
|
|
|
|
({template().locationEnd.x}, {template().locationEnd.y})
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<Show
|
|
|
|
<Show
|
|
|
|
when={displayImagePreview()}
|
|
|
|
when={displayImagePreview()}
|
|
|
|
fallback={
|
|
|
|
fallback={
|
|
|
|
<a
|
|
|
|
<a href="#" onClick={(event) => setDisplayImagePreview(true)}>
|
|
|
|
href="#"
|
|
|
|
|
|
|
|
onClick={
|
|
|
|
|
|
|
|
(event) => setDisplayImagePreview(true)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
Preview
|
|
|
|
Preview
|
|
|
|
</a>
|
|
|
|
</a>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<img class={styles.templateImagePreview} src={`/thrimshim/template/${encodeURIComponent(template().name)}.png`} />
|
|
|
|
<img
|
|
|
|
|
|
|
|
class={styles.templateImagePreview}
|
|
|
|
|
|
|
|
src={`/thrimshim/template/${encodeURIComponent(template().name)}.png`}
|
|
|
|
|
|
|
|
/>
|
|
|
|
</Show>
|
|
|
|
</Show>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<button
|
|
|
|
<button type="button" onClick={(event) => setEditing(true)}>
|
|
|
|
type="button"
|
|
|
|
|
|
|
|
onClick={
|
|
|
|
|
|
|
|
(event) => setEditing(true)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
Edit
|
|
|
|
Edit
|
|
|
|
</button>
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
@ -226,28 +241,92 @@ const ThumbnailManager: Component = () => {
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
(
|
|
|
|
(
|
|
|
|
<input type="number" name="cropstartx" placeholder="X" min={0} step={1} class={styles.templateCoord} value={template().cropStart.x} />
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
name="cropstartx"
|
|
|
|
|
|
|
|
placeholder="X"
|
|
|
|
|
|
|
|
min={0}
|
|
|
|
|
|
|
|
step={1}
|
|
|
|
|
|
|
|
class={styles.templateCoord}
|
|
|
|
|
|
|
|
value={template().cropStart.x}
|
|
|
|
|
|
|
|
/>
|
|
|
|
,
|
|
|
|
,
|
|
|
|
<input type="number" name="cropstarty" placeholder="Y" min={0} step={1} class={styles.templateCoord} value={template().cropStart.y} />
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
name="cropstarty"
|
|
|
|
|
|
|
|
placeholder="Y"
|
|
|
|
|
|
|
|
min={0}
|
|
|
|
|
|
|
|
step={1}
|
|
|
|
|
|
|
|
class={styles.templateCoord}
|
|
|
|
|
|
|
|
value={template().cropStart.y}
|
|
|
|
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
<br />
|
|
|
|
<br />
|
|
|
|
(
|
|
|
|
(
|
|
|
|
<input type="number" name="cropendx" placeholder="X" min={0} step={1} class={styles.templateCoord} value={template().cropEnd.x} />
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
name="cropendx"
|
|
|
|
|
|
|
|
placeholder="X"
|
|
|
|
|
|
|
|
min={0}
|
|
|
|
|
|
|
|
step={1}
|
|
|
|
|
|
|
|
class={styles.templateCoord}
|
|
|
|
|
|
|
|
value={template().cropEnd.x}
|
|
|
|
|
|
|
|
/>
|
|
|
|
,
|
|
|
|
,
|
|
|
|
<input type="number" name="cropendy" placeholder="Y" min={0} step={1} class={styles.templateCoord} value={template().cropEnd.y} />
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
name="cropendy"
|
|
|
|
|
|
|
|
placeholder="Y"
|
|
|
|
|
|
|
|
min={0}
|
|
|
|
|
|
|
|
step={1}
|
|
|
|
|
|
|
|
class={styles.templateCoord}
|
|
|
|
|
|
|
|
value={template().cropEnd.y}
|
|
|
|
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
(
|
|
|
|
(
|
|
|
|
<input type="number" name="locstartx" placeholder="X" min={0} step={1} class={styles.templateCoord} value={template().locationStart.x} />
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
name="locstartx"
|
|
|
|
|
|
|
|
placeholder="X"
|
|
|
|
|
|
|
|
min={0}
|
|
|
|
|
|
|
|
step={1}
|
|
|
|
|
|
|
|
class={styles.templateCoord}
|
|
|
|
|
|
|
|
value={template().locationStart.x}
|
|
|
|
|
|
|
|
/>
|
|
|
|
,
|
|
|
|
,
|
|
|
|
<input type="number" name="locstarty" placeholder="Y" min={0} step={1} class={styles.templateCoord} value={template().locationStart.y} />
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
name="locstarty"
|
|
|
|
|
|
|
|
placeholder="Y"
|
|
|
|
|
|
|
|
min={0}
|
|
|
|
|
|
|
|
step={1}
|
|
|
|
|
|
|
|
class={styles.templateCoord}
|
|
|
|
|
|
|
|
value={template().locationStart.y}
|
|
|
|
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
<br />
|
|
|
|
<br />
|
|
|
|
(
|
|
|
|
(
|
|
|
|
<input type="number" name="locendx" placeholder="X" min={0} step={1} class={styles.templateCoord} value={template().locationEnd.x} />
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
name="locendx"
|
|
|
|
|
|
|
|
placeholder="X"
|
|
|
|
|
|
|
|
min={0}
|
|
|
|
|
|
|
|
step={1}
|
|
|
|
|
|
|
|
class={styles.templateCoord}
|
|
|
|
|
|
|
|
value={template().locationEnd.x}
|
|
|
|
|
|
|
|
/>
|
|
|
|
,
|
|
|
|
,
|
|
|
|
<input type="number" name="locendy" placeholder="Y" min={0} step={1} class={styles.templateCoord} value={template().locationEnd.y} />
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
|
|
name="locendy"
|
|
|
|
|
|
|
|
placeholder="Y"
|
|
|
|
|
|
|
|
min={0}
|
|
|
|
|
|
|
|
step={1}
|
|
|
|
|
|
|
|
class={styles.templateCoord}
|
|
|
|
|
|
|
|
value={template().locationEnd.y}
|
|
|
|
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
@ -270,7 +349,13 @@ const ThumbnailManager: Component = () => {
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<form
|
|
|
|
<form
|
|
|
|
onSubmit={async (event) => {
|
|
|
|
onSubmit={async (event) => {
|
|
|
|
const submitData = await submitHandler("", true, newTemplateErrors, setNewTemplateErrors, event);
|
|
|
|
const submitData = await submitHandler(
|
|
|
|
|
|
|
|
"",
|
|
|
|
|
|
|
|
true,
|
|
|
|
|
|
|
|
newTemplateErrors,
|
|
|
|
|
|
|
|
setNewTemplateErrors,
|
|
|
|
|
|
|
|
event,
|
|
|
|
|
|
|
|
);
|
|
|
|
if (submitData) {
|
|
|
|
if (submitData) {
|
|
|
|
setTemplates((templateList) => [...templateList, submitData]);
|
|
|
|
setTemplates((templateList) => [...templateList, submitData]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|