mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-07 04:47:55 +02:00
support for saving updates with CTRL+s
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
This commit is contained in:
@@ -1,7 +1,35 @@
|
||||
<script>
|
||||
import { createEventDispatcher, onMount, onDestroy } from 'svelte';
|
||||
|
||||
export let bindTo = null;
|
||||
|
||||
$: if (formElement) {
|
||||
bindTo = formElement;
|
||||
}
|
||||
export let isSubmitting = false;
|
||||
export let novalidate = false;
|
||||
export let modalMode = null; // 'create', 'update', 'copy'
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let formElement = null;
|
||||
|
||||
function handleKeydown(event) {
|
||||
if (event.ctrlKey && event.key === 's') {
|
||||
// Only trigger if the form or its descendants have focus and we're in update mode
|
||||
if (modalMode === 'update' && formElement && formElement.contains(document.activeElement)) {
|
||||
event.preventDefault();
|
||||
dispatch('submit', { ...event, saveOnly: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
window.addEventListener('keydown', handleKeydown);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
window.removeEventListener('keydown', handleKeydown);
|
||||
});
|
||||
</script>
|
||||
|
||||
<form
|
||||
@@ -9,7 +37,7 @@
|
||||
inert={isSubmitting}
|
||||
class="grid grid-cols-3 grid-rows-1 w-full h-full flex-col bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 transition-colors duration-200"
|
||||
class:opacity-70={isSubmitting}
|
||||
bind:this={bindTo}
|
||||
bind:this={formElement}
|
||||
{novalidate}
|
||||
>
|
||||
<slot />
|
||||
|
||||
@@ -126,14 +126,15 @@
|
||||
return [];
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const onSubmit = async (event) => {
|
||||
try {
|
||||
isSubmitting = true;
|
||||
const saveOnly = event?.detail?.saveOnly || false;
|
||||
if (modalMode === 'create' || modalMode === 'copy') {
|
||||
await onClickCreate();
|
||||
return;
|
||||
} else {
|
||||
await onClickUpdate();
|
||||
await onClickUpdate(saveOnly);
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
@@ -157,15 +158,17 @@
|
||||
}
|
||||
};
|
||||
|
||||
const onClickUpdate = async () => {
|
||||
const onClickUpdate = async (saveOnly = false) => {
|
||||
try {
|
||||
const res = await api.apiSender.update(formValues);
|
||||
if (!res.success) {
|
||||
modalError = res.error;
|
||||
throw res.error;
|
||||
}
|
||||
addToast('Updated API sender', 'Success');
|
||||
closeEditModal();
|
||||
addToast(saveOnly ? 'API sender saved' : 'Updated API sender', 'Success');
|
||||
if (!saveOnly) {
|
||||
closeEditModal();
|
||||
}
|
||||
refreshConfigurations();
|
||||
} catch (err) {
|
||||
console.error('failed to update API sender:', err);
|
||||
@@ -352,7 +355,7 @@
|
||||
{/each}
|
||||
</Table>
|
||||
<Modal headerText={modalText} visible={isModalVisible} onClose={closeCreateModal} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting} {modalMode}>
|
||||
<FormColumns>
|
||||
<FormColumn>
|
||||
<!-- Basic Information Section -->
|
||||
|
||||
@@ -172,7 +172,8 @@
|
||||
return null;
|
||||
};
|
||||
|
||||
const onSubmitPageUpdate = async () => {
|
||||
const onSubmitPageUpdate = async (event) => {
|
||||
const saveOnly = event?.detail?.saveOnly || false;
|
||||
try {
|
||||
isSubmitting = true;
|
||||
updateContentError = '';
|
||||
@@ -218,20 +219,23 @@
|
||||
updateContentError = res.error;
|
||||
return;
|
||||
}
|
||||
addToast('Domain updated', 'Success');
|
||||
closeAllModals();
|
||||
addToast(saveOnly ? 'Domain content saved' : 'Domain updated', 'Success');
|
||||
if (!saveOnly) {
|
||||
closeAllModals();
|
||||
}
|
||||
refreshDomains();
|
||||
} catch (e) {
|
||||
addToast('Failed to update domain', 'Error');
|
||||
addToast(saveOnly ? 'Failed to save domain content' : 'Failed to update domain', 'Error');
|
||||
console.error('failed to update domain', e);
|
||||
} finally {
|
||||
isSubmitting = false;
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const onSubmit = async (event) => {
|
||||
try {
|
||||
// reset validate
|
||||
const saveOnly = event?.detail?.saveOnly || false;
|
||||
managedTLSInputElement?.setCustomValidity('');
|
||||
ownManagedTLSInputElement?.setCustomValidity('');
|
||||
ownManagedTLSKeyElement?.setCustomValidity('');
|
||||
@@ -262,7 +266,7 @@
|
||||
await onClickCreate();
|
||||
return;
|
||||
} else {
|
||||
await onClickUpdate();
|
||||
await onClickUpdate(saveOnly);
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
@@ -305,7 +309,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
const onClickUpdate = async () => {
|
||||
const onClickUpdate = async (saveOnly = false) => {
|
||||
modalError = '';
|
||||
// clear site contents if not hosting a website or if proxy domain
|
||||
if (!formValues.hostWebsite || isProxyDomain) {
|
||||
@@ -350,11 +354,13 @@
|
||||
modalError = res.error;
|
||||
return;
|
||||
}
|
||||
addToast('Domain updated', 'Success');
|
||||
closeAllModals();
|
||||
addToast(saveOnly ? 'Domain saved' : 'Domain updated', 'Success');
|
||||
if (!saveOnly) {
|
||||
closeAllModals();
|
||||
}
|
||||
refreshDomains();
|
||||
} catch (e) {
|
||||
addToast('Failed to update domain', 'Error');
|
||||
addToast(saveOnly ? 'Failed to save domain' : 'Failed to update domain', 'Error');
|
||||
console.error('failed to update domain', e);
|
||||
}
|
||||
};
|
||||
@@ -716,7 +722,7 @@
|
||||
onClose={closeAllModals}
|
||||
{isSubmitting}
|
||||
>
|
||||
<FormGrid novalidate on:submit={onSubmit} bind:bindTo={form} {isSubmitting}>
|
||||
<FormGrid novalidate on:submit={onSubmit} bind:bindTo={form} {isSubmitting} {modalMode}>
|
||||
<FormColumns>
|
||||
<FormColumn>
|
||||
<!-- Domain Information Section -->
|
||||
@@ -821,7 +827,12 @@
|
||||
onClose={closeAllModals}
|
||||
{isSubmitting}
|
||||
>
|
||||
<FormGrid on:submit={onSubmitPageUpdate} bind:bindTo={contentForm} {isSubmitting}>
|
||||
<FormGrid
|
||||
on:submit={onSubmitPageUpdate}
|
||||
bind:bindTo={contentForm}
|
||||
{isSubmitting}
|
||||
modalMode="update"
|
||||
>
|
||||
<Editor
|
||||
contentType="domain"
|
||||
baseURL={formValues.name}
|
||||
@@ -839,7 +850,12 @@
|
||||
onClose={closeAllModals}
|
||||
{isSubmitting}
|
||||
>
|
||||
<FormGrid on:submit={onSubmitPageUpdate} bind:bindTo={contentNotFoundForm} {isSubmitting}>
|
||||
<FormGrid
|
||||
on:submit={onSubmitPageUpdate}
|
||||
bind:bindTo={contentNotFoundForm}
|
||||
{isSubmitting}
|
||||
modalMode="update"
|
||||
>
|
||||
<Editor
|
||||
contentType="domain"
|
||||
baseURL={formValues.name}
|
||||
|
||||
@@ -137,14 +137,15 @@
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const onSubmit = async (event) => {
|
||||
try {
|
||||
isSubmitting = true;
|
||||
const saveOnly = event?.detail?.saveOnly || false;
|
||||
if (modalMode === 'create' || modalMode === 'copy') {
|
||||
await onClickCreate();
|
||||
return;
|
||||
} else {
|
||||
await onClickUpdate();
|
||||
await onClickUpdate(saveOnly);
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
@@ -176,7 +177,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
const onClickUpdate = async () => {
|
||||
const onClickUpdate = async (saveOnly = false) => {
|
||||
try {
|
||||
const res = await api.email.update({
|
||||
id: formValues.id,
|
||||
@@ -192,11 +193,13 @@
|
||||
return;
|
||||
}
|
||||
modalError = '';
|
||||
closeModal();
|
||||
addToast('Email updated', 'Success');
|
||||
addToast(saveOnly ? 'Email saved' : 'Email updated', 'Success');
|
||||
if (!saveOnly) {
|
||||
closeModal();
|
||||
}
|
||||
refreshEmails();
|
||||
} catch (e) {
|
||||
addToast('Failed to update email', 'Error');
|
||||
addToast(saveOnly ? 'Failed to save email' : 'Failed to update email', 'Error');
|
||||
console.error('failed to update email', e);
|
||||
}
|
||||
};
|
||||
@@ -423,7 +426,7 @@
|
||||
{/each}
|
||||
</Table>
|
||||
<Modal headerText={modalText} visible={isModalVisible} onClose={closeModal} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting} {modalMode}>
|
||||
<Editor contentType="email" {domainMap} bind:value={formValues.content}>
|
||||
<div class="flex flex-col lg:flex-row w-full pl-4">
|
||||
<div class="flex flex-col lg:flex-row justify-between w-1/3">
|
||||
|
||||
@@ -140,14 +140,15 @@
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const onSubmit = async (event) => {
|
||||
try {
|
||||
isSubmitting = true;
|
||||
const saveOnly = event?.detail?.saveOnly || false;
|
||||
if (modalMode === 'create' || modalMode === 'copy') {
|
||||
await create();
|
||||
return;
|
||||
} else {
|
||||
await update();
|
||||
await update(saveOnly);
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
@@ -171,7 +172,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
const update = async () => {
|
||||
const update = async (saveOnly = false) => {
|
||||
try {
|
||||
const updateData = {
|
||||
name: formValues.name,
|
||||
@@ -183,11 +184,13 @@
|
||||
formError = res.error;
|
||||
return;
|
||||
}
|
||||
addToast('Page updated', 'Success');
|
||||
closeModal();
|
||||
addToast(saveOnly ? 'Page saved' : 'Page updated', 'Success');
|
||||
if (!saveOnly) {
|
||||
closeModal();
|
||||
}
|
||||
refreshPages();
|
||||
} catch (e) {
|
||||
addToast('Failed to update page', 'Error');
|
||||
addToast(saveOnly ? 'Failed to save page' : 'Failed to update page', 'Error');
|
||||
console.error('failed to update page', e);
|
||||
}
|
||||
};
|
||||
@@ -359,7 +362,7 @@
|
||||
{/each}
|
||||
</Table>
|
||||
<Modal headerText={modalText} visible={isModalVisible} onClose={closeModal} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting} {modalMode}>
|
||||
<Editor contentType="page" {domainMap} bind:value={formValues.content}>
|
||||
<div class="pl-4">
|
||||
<TextField
|
||||
|
||||
@@ -144,14 +144,15 @@ portal.example.com:
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const onSubmit = async (event) => {
|
||||
try {
|
||||
isSubmitting = true;
|
||||
const saveOnly = event?.detail?.saveOnly || false;
|
||||
if (modalMode === 'create' || modalMode === 'copy') {
|
||||
await create();
|
||||
return;
|
||||
} else {
|
||||
await update();
|
||||
await update(saveOnly);
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
@@ -185,7 +186,7 @@ portal.example.com:
|
||||
}
|
||||
};
|
||||
|
||||
const update = async () => {
|
||||
const update = async (saveOnly = false) => {
|
||||
try {
|
||||
const updateData = {
|
||||
name: formValues.name,
|
||||
@@ -199,11 +200,13 @@ portal.example.com:
|
||||
formError = res.error;
|
||||
return;
|
||||
}
|
||||
addToast('Proxy updated', 'Success');
|
||||
closeModal();
|
||||
addToast(saveOnly ? 'Proxy saved' : 'Proxy updated', 'Success');
|
||||
if (!saveOnly) {
|
||||
closeModal();
|
||||
}
|
||||
refreshProxies();
|
||||
} catch (e) {
|
||||
addToast('Failed to update Proxy', 'Error');
|
||||
addToast(saveOnly ? 'Failed to save Proxy' : 'Failed to update Proxy', 'Error');
|
||||
console.error('failed to update Proxy', e);
|
||||
}
|
||||
};
|
||||
@@ -372,7 +375,7 @@ portal.example.com:
|
||||
{/each}
|
||||
</Table>
|
||||
<Modal headerText={modalText} visible={isModalVisible} onClose={closeModal} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting} {modalMode}>
|
||||
<div class="col-span-3 w-full overflow-y-auto px-6 py-4 space-y-8">
|
||||
<!-- Basic Information Section -->
|
||||
<div class="w-full">
|
||||
|
||||
Reference in New Issue
Block a user